1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <asm/system_info.h>
17#include <asm/ptrace.h>
18#include <linux/bug.h>
19
20#include "probes.h"
21
22
23#ifndef find_str_pc_offset
24
25
26
27
28
29
30
31
32int str_pc_offset;
33
34void __init find_str_pc_offset(void)
35{
36 int addr, scratch, ret;
37
38 __asm__ (
39 "sub %[ret], pc, #4 \n\t"
40 "str pc, %[addr] \n\t"
41 "ldr %[scr], %[addr] \n\t"
42 "sub %[ret], %[scr], %[ret] \n\t"
43 : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
44
45 str_pc_offset = ret;
46}
47
48#endif
49
50
51#ifndef test_load_write_pc_interworking
52
53bool load_write_pc_interworks;
54
55void __init test_load_write_pc_interworking(void)
56{
57 int arch = cpu_architecture();
58 BUG_ON(arch == CPU_ARCH_UNKNOWN);
59 load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
60}
61
62#endif
63
64
65#ifndef test_alu_write_pc_interworking
66
67bool alu_write_pc_interworks;
68
69void __init test_alu_write_pc_interworking(void)
70{
71 int arch = cpu_architecture();
72 BUG_ON(arch == CPU_ARCH_UNKNOWN);
73 alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7;
74}
75
76#endif
77
78
79void __init arm_probes_decode_init(void)
80{
81 find_str_pc_offset();
82 test_load_write_pc_interworking();
83 test_alu_write_pc_interworking();
84}
85
86
87static unsigned long __kprobes __check_eq(unsigned long cpsr)
88{
89 return cpsr & PSR_Z_BIT;
90}
91
92static unsigned long __kprobes __check_ne(unsigned long cpsr)
93{
94 return (~cpsr) & PSR_Z_BIT;
95}
96
97static unsigned long __kprobes __check_cs(unsigned long cpsr)
98{
99 return cpsr & PSR_C_BIT;
100}
101
102static unsigned long __kprobes __check_cc(unsigned long cpsr)
103{
104 return (~cpsr) & PSR_C_BIT;
105}
106
107static unsigned long __kprobes __check_mi(unsigned long cpsr)
108{
109 return cpsr & PSR_N_BIT;
110}
111
112static unsigned long __kprobes __check_pl(unsigned long cpsr)
113{
114 return (~cpsr) & PSR_N_BIT;
115}
116
117static unsigned long __kprobes __check_vs(unsigned long cpsr)
118{
119 return cpsr & PSR_V_BIT;
120}
121
122static unsigned long __kprobes __check_vc(unsigned long cpsr)
123{
124 return (~cpsr) & PSR_V_BIT;
125}
126
127static unsigned long __kprobes __check_hi(unsigned long cpsr)
128{
129 cpsr &= ~(cpsr >> 1);
130 return cpsr & PSR_C_BIT;
131}
132
133static unsigned long __kprobes __check_ls(unsigned long cpsr)
134{
135 cpsr &= ~(cpsr >> 1);
136 return (~cpsr) & PSR_C_BIT;
137}
138
139static unsigned long __kprobes __check_ge(unsigned long cpsr)
140{
141 cpsr ^= (cpsr << 3);
142 return (~cpsr) & PSR_N_BIT;
143}
144
145static unsigned long __kprobes __check_lt(unsigned long cpsr)
146{
147 cpsr ^= (cpsr << 3);
148 return cpsr & PSR_N_BIT;
149}
150
151static unsigned long __kprobes __check_gt(unsigned long cpsr)
152{
153 unsigned long temp = cpsr ^ (cpsr << 3);
154 temp |= (cpsr << 1);
155 return (~temp) & PSR_N_BIT;
156}
157
158static unsigned long __kprobes __check_le(unsigned long cpsr)
159{
160 unsigned long temp = cpsr ^ (cpsr << 3);
161 temp |= (cpsr << 1);
162 return temp & PSR_N_BIT;
163}
164
165static unsigned long __kprobes __check_al(unsigned long cpsr)
166{
167 return true;
168}
169
170probes_check_cc * const probes_condition_checks[16] = {
171 &__check_eq, &__check_ne, &__check_cs, &__check_cc,
172 &__check_mi, &__check_pl, &__check_vs, &__check_vc,
173 &__check_hi, &__check_ls, &__check_ge, &__check_lt,
174 &__check_gt, &__check_le, &__check_al, &__check_al
175};
176
177
178void __kprobes probes_simulate_nop(probes_opcode_t opcode,
179 struct arch_probes_insn *asi,
180 struct pt_regs *regs)
181{
182}
183
184void __kprobes probes_emulate_none(probes_opcode_t opcode,
185 struct arch_probes_insn *asi,
186 struct pt_regs *regs)
187{
188 asi->insn_fn();
189}
190
191
192
193
194
195
196
197
198static probes_opcode_t __kprobes
199prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
200 bool thumb)
201{
202#ifdef CONFIG_THUMB2_KERNEL
203 if (thumb) {
204 u16 *thumb_insn = (u16 *)asi->insn;
205
206 thumb_insn[1] = __opcode_to_mem_thumb16(0x4770);
207 thumb_insn[2] = __opcode_to_mem_thumb16(0x4770);
208 return insn;
209 }
210 asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e);
211#else
212 asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e);
213#endif
214
215 if (insn < 0xe0000000)
216 insn = (insn | 0xe0000000) & ~0x10000000;
217 return insn;
218}
219
220
221
222
223
224static void __kprobes
225set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
226 bool thumb)
227{
228#ifdef CONFIG_THUMB2_KERNEL
229 if (thumb) {
230 u16 *ip = (u16 *)asi->insn;
231 if (is_wide_instruction(insn))
232 *ip++ = __opcode_to_mem_thumb16(insn >> 16);
233 *ip++ = __opcode_to_mem_thumb16(insn);
234 return;
235 }
236#endif
237 asi->insn[0] = __opcode_to_mem_arm(insn);
238}
239
240
241
242
243
244
245
246
247
248
249#define INSN_NEW_BITS 0x00020103
250
251
252#define INSN_SAMEAS16_BITS 0x22222222
253
254
255
256
257
258
259
260
261static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify)
262{
263 probes_opcode_t insn = *pinsn;
264 probes_opcode_t mask = 0xf;
265
266 for (; regs != 0; regs >>= 4, mask <<= 4) {
267
268 probes_opcode_t new_bits = INSN_NEW_BITS;
269
270 switch (regs & 0xf) {
271
272 case REG_TYPE_NONE:
273
274 continue;
275
276 case REG_TYPE_ANY:
277
278 break;
279
280 case REG_TYPE_SAMEAS16:
281
282 new_bits = INSN_SAMEAS16_BITS;
283 break;
284
285 case REG_TYPE_SP:
286
287 if ((insn ^ 0xdddddddd) & mask)
288 goto reject;
289 break;
290
291 case REG_TYPE_PC:
292
293 if ((insn ^ 0xffffffff) & mask)
294 goto reject;
295 break;
296
297 case REG_TYPE_NOSP:
298
299 if (((insn ^ 0xdddddddd) & mask) == 0)
300 goto reject;
301 break;
302
303 case REG_TYPE_NOSPPC:
304 case REG_TYPE_NOSPPCX:
305
306 if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
307 goto reject;
308 break;
309
310 case REG_TYPE_NOPCWB:
311 if (!is_writeback(insn))
312 break;
313
314 case REG_TYPE_NOPC:
315 case REG_TYPE_NOPCX:
316
317 if (((insn ^ 0xffffffff) & mask) == 0)
318 goto reject;
319 break;
320 }
321
322
323 insn &= ~mask;
324 insn |= new_bits & mask;
325 }
326
327 if (modify)
328 *pinsn = insn;
329
330 return true;
331
332reject:
333 return false;
334}
335
336static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
337 [DECODE_TYPE_TABLE] = sizeof(struct decode_table),
338 [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),
339 [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),
340 [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),
341 [DECODE_TYPE_OR] = sizeof(struct decode_or),
342 [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)
343};
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388int __kprobes
389probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi,
390 const union decode_item *table, bool thumb,
391 bool emulate, const union decode_action *actions)
392{
393 const struct decode_header *h = (struct decode_header *)table;
394 const struct decode_header *next;
395 bool matched = false;
396
397 if (emulate)
398 insn = prepare_emulated_insn(insn, asi, thumb);
399
400 for (;; h = next) {
401 enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
402 u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
403
404 if (type == DECODE_TYPE_END)
405 return INSN_REJECTED;
406
407 next = (struct decode_header *)
408 ((uintptr_t)h + decode_struct_sizes[type]);
409
410 if (!matched && (insn & h->mask.bits) != h->value.bits)
411 continue;
412
413 if (!decode_regs(&insn, regs, emulate))
414 return INSN_REJECTED;
415
416 switch (type) {
417
418 case DECODE_TYPE_TABLE: {
419 struct decode_table *d = (struct decode_table *)h;
420 next = (struct decode_header *)d->table.table;
421 break;
422 }
423
424 case DECODE_TYPE_CUSTOM: {
425 struct decode_custom *d = (struct decode_custom *)h;
426 return actions[d->decoder.action].decoder(insn, asi, h);
427 }
428
429 case DECODE_TYPE_SIMULATE: {
430 struct decode_simulate *d = (struct decode_simulate *)h;
431 asi->insn_handler = actions[d->handler.action].handler;
432 return INSN_GOOD_NO_SLOT;
433 }
434
435 case DECODE_TYPE_EMULATE: {
436 struct decode_emulate *d = (struct decode_emulate *)h;
437
438 if (!emulate)
439 return actions[d->handler.action].decoder(insn,
440 asi, h);
441
442 asi->insn_handler = actions[d->handler.action].handler;
443 set_emulated_insn(insn, asi, thumb);
444 return INSN_GOOD;
445 }
446
447 case DECODE_TYPE_OR:
448 matched = true;
449 break;
450
451 case DECODE_TYPE_REJECT:
452 default:
453 return INSN_REJECTED;
454 }
455 }
456}
457