~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to arch/arm/kernel/kprobes-decode.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * arch/arm/kernel/kprobes-decode.c
3
 
 *
4
 
 * Copyright (C) 2006, 2007 Motorola Inc.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License version 2 as
8
 
 * published by the Free Software Foundation.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * General Public License for more details.
14
 
 */
15
 
 
16
 
/*
17
 
 * We do not have hardware single-stepping on ARM, This
18
 
 * effort is further complicated by the ARM not having a
19
 
 * "next PC" register.  Instructions that change the PC
20
 
 * can't be safely single-stepped in a MP environment, so
21
 
 * we have a lot of work to do:
22
 
 *
23
 
 * In the prepare phase:
24
 
 *   *) If it is an instruction that does anything
25
 
 *      with the CPU mode, we reject it for a kprobe.
26
 
 *      (This is out of laziness rather than need.  The
27
 
 *      instructions could be simulated.)
28
 
 *
29
 
 *   *) Otherwise, decode the instruction rewriting its
30
 
 *      registers to take fixed, ordered registers and
31
 
 *      setting a handler for it to run the instruction.
32
 
 *
33
 
 * In the execution phase by an instruction's handler:
34
 
 *
35
 
 *   *) If the PC is written to by the instruction, the
36
 
 *      instruction must be fully simulated in software.
37
 
 *
38
 
 *   *) Otherwise, a modified form of the instruction is
39
 
 *      directly executed.  Its handler calls the
40
 
 *      instruction in insn[0].  In insn[1] is a
41
 
 *      "mov pc, lr" to return.
42
 
 *
43
 
 *      Before calling, load up the reordered registers
44
 
 *      from the original instruction's registers.  If one
45
 
 *      of the original input registers is the PC, compute
46
 
 *      and adjust the appropriate input register.
47
 
 *
48
 
 *      After call completes, copy the output registers to
49
 
 *      the original instruction's original registers.
50
 
 *
51
 
 * We don't use a real breakpoint instruction since that
52
 
 * would have us in the kernel go from SVC mode to SVC
53
 
 * mode losing the link register.  Instead we use an
54
 
 * undefined instruction.  To simplify processing, the
55
 
 * undefined instruction used for kprobes must be reserved
56
 
 * exclusively for kprobes use.
57
 
 *
58
 
 * TODO: ifdef out some instruction decoding based on architecture.
59
 
 */
60
 
 
61
 
#include <linux/kernel.h>
62
 
#include <linux/kprobes.h>
63
 
 
64
 
#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
65
 
 
66
 
#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
67
 
 
68
 
#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
69
 
 
70
 
/*
71
 
 * Test if load/store instructions writeback the address register.
72
 
 * if P (bit 24) == 0 or W (bit 21) == 1
73
 
 */
74
 
#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
75
 
 
76
 
#define PSR_fs  (PSR_f|PSR_s)
77
 
 
78
 
#define KPROBE_RETURN_INSTRUCTION       0xe1a0f00e      /* mov pc, lr */
79
 
 
80
 
typedef long (insn_0arg_fn_t)(void);
81
 
typedef long (insn_1arg_fn_t)(long);
82
 
typedef long (insn_2arg_fn_t)(long, long);
83
 
typedef long (insn_3arg_fn_t)(long, long, long);
84
 
typedef long (insn_4arg_fn_t)(long, long, long, long);
85
 
typedef long long (insn_llret_0arg_fn_t)(void);
86
 
typedef long long (insn_llret_3arg_fn_t)(long, long, long);
87
 
typedef long long (insn_llret_4arg_fn_t)(long, long, long, long);
88
 
 
89
 
union reg_pair {
90
 
        long long       dr;
91
 
#ifdef __LITTLE_ENDIAN
92
 
        struct { long   r0, r1; };
93
 
#else
94
 
        struct { long   r1, r0; };
95
 
#endif
96
 
};
97
 
 
98
 
/*
99
 
 * For STR and STM instructions, an ARM core may choose to use either
100
 
 * a +8 or a +12 displacement from the current instruction's address.
101
 
 * Whichever value is chosen for a given core, it must be the same for
102
 
 * both instructions and may not change.  This function measures it.
103
 
 */
104
 
 
105
 
static int str_pc_offset;
106
 
 
107
 
static void __init find_str_pc_offset(void)
108
 
{
109
 
        int addr, scratch, ret;
110
 
 
111
 
        __asm__ (
112
 
                "sub    %[ret], pc, #4          \n\t"
113
 
                "str    pc, %[addr]             \n\t"
114
 
                "ldr    %[scr], %[addr]         \n\t"
115
 
                "sub    %[ret], %[scr], %[ret]  \n\t"
116
 
                : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
117
 
 
118
 
        str_pc_offset = ret;
119
 
}
120
 
 
121
 
/*
122
 
 * The insnslot_?arg_r[w]flags() functions below are to keep the
123
 
 * msr -> *fn -> mrs instruction sequences indivisible so that
124
 
 * the state of the CPSR flags aren't inadvertently modified
125
 
 * just before or just after the call.
126
 
 */
127
 
 
128
 
static inline long __kprobes
129
 
insnslot_0arg_rflags(long cpsr, insn_0arg_fn_t *fn)
130
 
{
131
 
        register long ret asm("r0");
132
 
 
133
 
        __asm__ __volatile__ (
134
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
135
 
                "mov    lr, pc                  \n\t"
136
 
                "mov    pc, %[fn]               \n\t"
137
 
                : "=r" (ret)
138
 
                : [cpsr] "r" (cpsr), [fn] "r" (fn)
139
 
                : "lr", "cc"
140
 
        );
141
 
        return ret;
142
 
}
143
 
 
144
 
static inline long long __kprobes
145
 
insnslot_llret_0arg_rflags(long cpsr, insn_llret_0arg_fn_t *fn)
146
 
{
147
 
        register long ret0 asm("r0");
148
 
        register long ret1 asm("r1");
149
 
        union reg_pair fnr;
150
 
 
151
 
        __asm__ __volatile__ (
152
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
153
 
                "mov    lr, pc                  \n\t"
154
 
                "mov    pc, %[fn]               \n\t"
155
 
                : "=r" (ret0), "=r" (ret1)
156
 
                : [cpsr] "r" (cpsr), [fn] "r" (fn)
157
 
                : "lr", "cc"
158
 
        );
159
 
        fnr.r0 = ret0;
160
 
        fnr.r1 = ret1;
161
 
        return fnr.dr;
162
 
}
163
 
 
164
 
static inline long __kprobes
165
 
insnslot_1arg_rflags(long r0, long cpsr, insn_1arg_fn_t *fn)
166
 
{
167
 
        register long rr0 asm("r0") = r0;
168
 
        register long ret asm("r0");
169
 
 
170
 
        __asm__ __volatile__ (
171
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
172
 
                "mov    lr, pc                  \n\t"
173
 
                "mov    pc, %[fn]               \n\t"
174
 
                : "=r" (ret)
175
 
                : "0" (rr0), [cpsr] "r" (cpsr), [fn] "r" (fn)
176
 
                : "lr", "cc"
177
 
        );
178
 
        return ret;
179
 
}
180
 
 
181
 
static inline long __kprobes
182
 
insnslot_2arg_rflags(long r0, long r1, long cpsr, insn_2arg_fn_t *fn)
183
 
{
184
 
        register long rr0 asm("r0") = r0;
185
 
        register long rr1 asm("r1") = r1;
186
 
        register long ret asm("r0");
187
 
 
188
 
        __asm__ __volatile__ (
189
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
190
 
                "mov    lr, pc                  \n\t"
191
 
                "mov    pc, %[fn]               \n\t"
192
 
                : "=r" (ret)
193
 
                : "0" (rr0), "r" (rr1),
194
 
                  [cpsr] "r" (cpsr), [fn] "r" (fn)
195
 
                : "lr", "cc"
196
 
        );
197
 
        return ret;
198
 
}
199
 
 
200
 
static inline long __kprobes
201
 
insnslot_3arg_rflags(long r0, long r1, long r2, long cpsr, insn_3arg_fn_t *fn)
202
 
{
203
 
        register long rr0 asm("r0") = r0;
204
 
        register long rr1 asm("r1") = r1;
205
 
        register long rr2 asm("r2") = r2;
206
 
        register long ret asm("r0");
207
 
 
208
 
        __asm__ __volatile__ (
209
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
210
 
                "mov    lr, pc                  \n\t"
211
 
                "mov    pc, %[fn]               \n\t"
212
 
                : "=r" (ret)
213
 
                : "0" (rr0), "r" (rr1), "r" (rr2),
214
 
                  [cpsr] "r" (cpsr), [fn] "r" (fn)
215
 
                : "lr", "cc"
216
 
        );
217
 
        return ret;
218
 
}
219
 
 
220
 
static inline long long __kprobes
221
 
insnslot_llret_3arg_rflags(long r0, long r1, long r2, long cpsr,
222
 
                           insn_llret_3arg_fn_t *fn)
223
 
{
224
 
        register long rr0 asm("r0") = r0;
225
 
        register long rr1 asm("r1") = r1;
226
 
        register long rr2 asm("r2") = r2;
227
 
        register long ret0 asm("r0");
228
 
        register long ret1 asm("r1");
229
 
        union reg_pair fnr;
230
 
 
231
 
        __asm__ __volatile__ (
232
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
233
 
                "mov    lr, pc                  \n\t"
234
 
                "mov    pc, %[fn]               \n\t"
235
 
                : "=r" (ret0), "=r" (ret1)
236
 
                : "0" (rr0), "r" (rr1), "r" (rr2),
237
 
                  [cpsr] "r" (cpsr), [fn] "r" (fn)
238
 
                : "lr", "cc"
239
 
        );
240
 
        fnr.r0 = ret0;
241
 
        fnr.r1 = ret1;
242
 
        return fnr.dr;
243
 
}
244
 
 
245
 
static inline long __kprobes
246
 
insnslot_4arg_rflags(long r0, long r1, long r2, long r3, long cpsr,
247
 
                     insn_4arg_fn_t *fn)
248
 
{
249
 
        register long rr0 asm("r0") = r0;
250
 
        register long rr1 asm("r1") = r1;
251
 
        register long rr2 asm("r2") = r2;
252
 
        register long rr3 asm("r3") = r3;
253
 
        register long ret asm("r0");
254
 
 
255
 
        __asm__ __volatile__ (
256
 
                "msr    cpsr_fs, %[cpsr]        \n\t"
257
 
                "mov    lr, pc                  \n\t"
258
 
                "mov    pc, %[fn]               \n\t"
259
 
                : "=r" (ret)
260
 
                : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
261
 
                  [cpsr] "r" (cpsr), [fn] "r" (fn)
262
 
                : "lr", "cc"
263
 
        );
264
 
        return ret;
265
 
}
266
 
 
267
 
static inline long __kprobes
268
 
insnslot_1arg_rwflags(long r0, long *cpsr, insn_1arg_fn_t *fn)
269
 
{
270
 
        register long rr0 asm("r0") = r0;
271
 
        register long ret asm("r0");
272
 
        long oldcpsr = *cpsr;
273
 
        long newcpsr;
274
 
 
275
 
        __asm__ __volatile__ (
276
 
                "msr    cpsr_fs, %[oldcpsr]     \n\t"
277
 
                "mov    lr, pc                  \n\t"
278
 
                "mov    pc, %[fn]               \n\t"
279
 
                "mrs    %[newcpsr], cpsr        \n\t"
280
 
                : "=r" (ret), [newcpsr] "=r" (newcpsr)
281
 
                : "0" (rr0), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
282
 
                : "lr", "cc"
283
 
        );
284
 
        *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
285
 
        return ret;
286
 
}
287
 
 
288
 
static inline long __kprobes
289
 
insnslot_2arg_rwflags(long r0, long r1, long *cpsr, insn_2arg_fn_t *fn)
290
 
{
291
 
        register long rr0 asm("r0") = r0;
292
 
        register long rr1 asm("r1") = r1;
293
 
        register long ret asm("r0");
294
 
        long oldcpsr = *cpsr;
295
 
        long newcpsr;
296
 
 
297
 
        __asm__ __volatile__ (
298
 
                "msr    cpsr_fs, %[oldcpsr]     \n\t"
299
 
                "mov    lr, pc                  \n\t"
300
 
                "mov    pc, %[fn]               \n\t"
301
 
                "mrs    %[newcpsr], cpsr        \n\t"
302
 
                : "=r" (ret), [newcpsr] "=r" (newcpsr)
303
 
                : "0" (rr0), "r" (rr1), [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
304
 
                : "lr", "cc"
305
 
        );
306
 
        *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
307
 
        return ret;
308
 
}
309
 
 
310
 
static inline long __kprobes
311
 
insnslot_3arg_rwflags(long r0, long r1, long r2, long *cpsr,
312
 
                      insn_3arg_fn_t *fn)
313
 
{
314
 
        register long rr0 asm("r0") = r0;
315
 
        register long rr1 asm("r1") = r1;
316
 
        register long rr2 asm("r2") = r2;
317
 
        register long ret asm("r0");
318
 
        long oldcpsr = *cpsr;
319
 
        long newcpsr;
320
 
 
321
 
        __asm__ __volatile__ (
322
 
                "msr    cpsr_fs, %[oldcpsr]     \n\t"
323
 
                "mov    lr, pc                  \n\t"
324
 
                "mov    pc, %[fn]               \n\t"
325
 
                "mrs    %[newcpsr], cpsr        \n\t"
326
 
                : "=r" (ret), [newcpsr] "=r" (newcpsr)
327
 
                : "0" (rr0), "r" (rr1), "r" (rr2),
328
 
                  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
329
 
                : "lr", "cc"
330
 
        );
331
 
        *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
332
 
        return ret;
333
 
}
334
 
 
335
 
static inline long __kprobes
336
 
insnslot_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
337
 
                      insn_4arg_fn_t *fn)
338
 
{
339
 
        register long rr0 asm("r0") = r0;
340
 
        register long rr1 asm("r1") = r1;
341
 
        register long rr2 asm("r2") = r2;
342
 
        register long rr3 asm("r3") = r3;
343
 
        register long ret asm("r0");
344
 
        long oldcpsr = *cpsr;
345
 
        long newcpsr;
346
 
 
347
 
        __asm__ __volatile__ (
348
 
                "msr    cpsr_fs, %[oldcpsr]     \n\t"
349
 
                "mov    lr, pc                  \n\t"
350
 
                "mov    pc, %[fn]               \n\t"
351
 
                "mrs    %[newcpsr], cpsr        \n\t"
352
 
                : "=r" (ret), [newcpsr] "=r" (newcpsr)
353
 
                : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
354
 
                  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
355
 
                : "lr", "cc"
356
 
        );
357
 
        *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
358
 
        return ret;
359
 
}
360
 
 
361
 
static inline long long __kprobes
362
 
insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
363
 
                            insn_llret_4arg_fn_t *fn)
364
 
{
365
 
        register long rr0 asm("r0") = r0;
366
 
        register long rr1 asm("r1") = r1;
367
 
        register long rr2 asm("r2") = r2;
368
 
        register long rr3 asm("r3") = r3;
369
 
        register long ret0 asm("r0");
370
 
        register long ret1 asm("r1");
371
 
        long oldcpsr = *cpsr;
372
 
        long newcpsr;
373
 
        union reg_pair fnr;
374
 
 
375
 
        __asm__ __volatile__ (
376
 
                "msr    cpsr_fs, %[oldcpsr]     \n\t"
377
 
                "mov    lr, pc                  \n\t"
378
 
                "mov    pc, %[fn]               \n\t"
379
 
                "mrs    %[newcpsr], cpsr        \n\t"
380
 
                : "=r" (ret0), "=r" (ret1), [newcpsr] "=r" (newcpsr)
381
 
                : "0" (rr0), "r" (rr1), "r" (rr2), "r" (rr3),
382
 
                  [oldcpsr] "r" (oldcpsr), [fn] "r" (fn)
383
 
                : "lr", "cc"
384
 
        );
385
 
        *cpsr = (oldcpsr & ~PSR_fs) | (newcpsr & PSR_fs);
386
 
        fnr.r0 = ret0;
387
 
        fnr.r1 = ret1;
388
 
        return fnr.dr;
389
 
}
390
 
 
391
 
/*
392
 
 * To avoid the complications of mimicing single-stepping on a
393
 
 * processor without a Next-PC or a single-step mode, and to
394
 
 * avoid having to deal with the side-effects of boosting, we
395
 
 * simulate or emulate (almost) all ARM instructions.
396
 
 *
397
 
 * "Simulation" is where the instruction's behavior is duplicated in
398
 
 * C code.  "Emulation" is where the original instruction is rewritten
399
 
 * and executed, often by altering its registers.
400
 
 *
401
 
 * By having all behavior of the kprobe'd instruction completed before
402
 
 * returning from the kprobe_handler(), all locks (scheduler and
403
 
 * interrupt) can safely be released.  There is no need for secondary
404
 
 * breakpoints, no race with MP or preemptable kernels, nor having to
405
 
 * clean up resources counts at a later time impacting overall system
406
 
 * performance.  By rewriting the instruction, only the minimum registers
407
 
 * need to be loaded and saved back optimizing performance.
408
 
 *
409
 
 * Calling the insnslot_*_rwflags version of a function doesn't hurt
410
 
 * anything even when the CPSR flags aren't updated by the
411
 
 * instruction.  It's just a little slower in return for saving
412
 
 * a little space by not having a duplicate function that doesn't
413
 
 * update the flags.  (The same optimization can be said for
414
 
 * instructions that do or don't perform register writeback)
415
 
 * Also, instructions can either read the flags, only write the
416
 
 * flags, or read and write the flags.  To save combinations
417
 
 * rather than for sheer performance, flag functions just assume
418
 
 * read and write of flags.
419
 
 */
420
 
 
421
 
static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
422
 
{
423
 
        kprobe_opcode_t insn = p->opcode;
424
 
        long iaddr = (long)p->addr;
425
 
        int disp  = branch_displacement(insn);
426
 
 
427
 
        if (insn & (1 << 24))
428
 
                regs->ARM_lr = iaddr + 4;
429
 
 
430
 
        regs->ARM_pc = iaddr + 8 + disp;
431
 
}
432
 
 
433
 
static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
434
 
{
435
 
        kprobe_opcode_t insn = p->opcode;
436
 
        long iaddr = (long)p->addr;
437
 
        int disp = branch_displacement(insn);
438
 
 
439
 
        regs->ARM_lr = iaddr + 4;
440
 
        regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
441
 
        regs->ARM_cpsr |= PSR_T_BIT;
442
 
}
443
 
 
444
 
static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
445
 
{
446
 
        kprobe_opcode_t insn = p->opcode;
447
 
        int rm = insn & 0xf;
448
 
        long rmv = regs->uregs[rm];
449
 
 
450
 
        if (insn & (1 << 5))
451
 
                regs->ARM_lr = (long)p->addr + 4;
452
 
 
453
 
        regs->ARM_pc = rmv & ~0x1;
454
 
        regs->ARM_cpsr &= ~PSR_T_BIT;
455
 
        if (rmv & 0x1)
456
 
                regs->ARM_cpsr |= PSR_T_BIT;
457
 
}
458
 
 
459
 
static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
460
 
{
461
 
        kprobe_opcode_t insn = p->opcode;
462
 
        int rd = (insn >> 12) & 0xf;
463
 
        unsigned long mask = 0xf8ff03df; /* Mask out execution state */
464
 
        regs->uregs[rd] = regs->ARM_cpsr & mask;
465
 
}
466
 
 
467
 
static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
468
 
{
469
 
        kprobe_opcode_t insn = p->opcode;
470
 
        int rn = (insn >> 16) & 0xf;
471
 
        int lbit = insn & (1 << 20);
472
 
        int wbit = insn & (1 << 21);
473
 
        int ubit = insn & (1 << 23);
474
 
        int pbit = insn & (1 << 24);
475
 
        long *addr = (long *)regs->uregs[rn];
476
 
        int reg_bit_vector;
477
 
        int reg_count;
478
 
 
479
 
        reg_count = 0;
480
 
        reg_bit_vector = insn & 0xffff;
481
 
        while (reg_bit_vector) {
482
 
                reg_bit_vector &= (reg_bit_vector - 1);
483
 
                ++reg_count;
484
 
        }
485
 
 
486
 
        if (!ubit)
487
 
                addr -= reg_count;
488
 
        addr += (!pbit == !ubit);
489
 
 
490
 
        reg_bit_vector = insn & 0xffff;
491
 
        while (reg_bit_vector) {
492
 
                int reg = __ffs(reg_bit_vector);
493
 
                reg_bit_vector &= (reg_bit_vector - 1);
494
 
                if (lbit)
495
 
                        regs->uregs[reg] = *addr++;
496
 
                else
497
 
                        *addr++ = regs->uregs[reg];
498
 
        }
499
 
 
500
 
        if (wbit) {
501
 
                if (!ubit)
502
 
                        addr -= reg_count;
503
 
                addr -= (!pbit == !ubit);
504
 
                regs->uregs[rn] = (long)addr;
505
 
        }
506
 
}
507
 
 
508
 
static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
509
 
{
510
 
        regs->ARM_pc = (long)p->addr + str_pc_offset;
511
 
        simulate_ldm1stm1(p, regs);
512
 
        regs->ARM_pc = (long)p->addr + 4;
513
 
}
514
 
 
515
 
static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
516
 
{
517
 
        regs->uregs[12] = regs->uregs[13];
518
 
}
519
 
 
520
 
static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
521
 
{
522
 
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
523
 
        kprobe_opcode_t insn = p->opcode;
524
 
        long ppc = (long)p->addr + 8;
525
 
        int rd = (insn >> 12) & 0xf;
526
 
        int rn = (insn >> 16) & 0xf;
527
 
        int rm = insn & 0xf;  /* rm may be invalid, don't care. */
528
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
529
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
530
 
 
531
 
        /* Not following the C calling convention here, so need asm(). */
532
 
        __asm__ __volatile__ (
533
 
                "ldr    r0, %[rn]       \n\t"
534
 
                "ldr    r1, %[rm]       \n\t"
535
 
                "msr    cpsr_fs, %[cpsr]\n\t"
536
 
                "mov    lr, pc          \n\t"
537
 
                "mov    pc, %[i_fn]     \n\t"
538
 
                "str    r0, %[rn]       \n\t"   /* in case of writeback */
539
 
                "str    r2, %[rd0]      \n\t"
540
 
                "str    r3, %[rd1]      \n\t"
541
 
                : [rn]  "+m" (rnv),
542
 
                  [rd0] "=m" (regs->uregs[rd]),
543
 
                  [rd1] "=m" (regs->uregs[rd+1])
544
 
                : [rm]   "m" (rmv),
545
 
                  [cpsr] "r" (regs->ARM_cpsr),
546
 
                  [i_fn] "r" (i_fn)
547
 
                : "r0", "r1", "r2", "r3", "lr", "cc"
548
 
        );
549
 
        if (is_writeback(insn))
550
 
                regs->uregs[rn] = rnv;
551
 
}
552
 
 
553
 
static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
554
 
{
555
 
        insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
556
 
        kprobe_opcode_t insn = p->opcode;
557
 
        long ppc = (long)p->addr + 8;
558
 
        int rd = (insn >> 12) & 0xf;
559
 
        int rn = (insn >> 16) & 0xf;
560
 
        int rm  = insn & 0xf;
561
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
562
 
        /* rm/rmv may be invalid, don't care. */
563
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
564
 
        long rnv_wb;
565
 
 
566
 
        rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
567
 
                                               regs->uregs[rd+1],
568
 
                                               regs->ARM_cpsr, i_fn);
569
 
        if (is_writeback(insn))
570
 
                regs->uregs[rn] = rnv_wb;
571
 
}
572
 
 
573
 
static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
574
 
{
575
 
        insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];
576
 
        kprobe_opcode_t insn = p->opcode;
577
 
        long ppc = (long)p->addr + 8;
578
 
        union reg_pair fnr;
579
 
        int rd = (insn >> 12) & 0xf;
580
 
        int rn = (insn >> 16) & 0xf;
581
 
        int rm = insn & 0xf;
582
 
        long rdv;
583
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
584
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
585
 
        long cpsr = regs->ARM_cpsr;
586
 
 
587
 
        fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
588
 
        if (rn != 15)
589
 
                regs->uregs[rn] = fnr.r0;  /* Save Rn in case of writeback. */
590
 
        rdv = fnr.r1;
591
 
 
592
 
        if (rd == 15) {
593
 
#if __LINUX_ARM_ARCH__ >= 5
594
 
                cpsr &= ~PSR_T_BIT;
595
 
                if (rdv & 0x1)
596
 
                        cpsr |= PSR_T_BIT;
597
 
                regs->ARM_cpsr = cpsr;
598
 
                rdv &= ~0x1;
599
 
#else
600
 
                rdv &= ~0x2;
601
 
#endif
602
 
        }
603
 
        regs->uregs[rd] = rdv;
604
 
}
605
 
 
606
 
static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
607
 
{
608
 
        insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
609
 
        kprobe_opcode_t insn = p->opcode;
610
 
        long iaddr = (long)p->addr;
611
 
        int rd = (insn >> 12) & 0xf;
612
 
        int rn = (insn >> 16) & 0xf;
613
 
        int rm = insn & 0xf;
614
 
        long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
615
 
        long rnv = (rn == 15) ? iaddr +  8 : regs->uregs[rn];
616
 
        long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
617
 
        long rnv_wb;
618
 
 
619
 
        rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
620
 
        if (rn != 15)
621
 
                regs->uregs[rn] = rnv_wb;  /* Save Rn in case of writeback. */
622
 
}
623
 
 
624
 
static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
625
 
{
626
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
627
 
        kprobe_opcode_t insn = p->opcode;
628
 
        int rd = (insn >> 12) & 0xf;
629
 
        int rm = insn & 0xf;
630
 
        long rmv = regs->uregs[rm];
631
 
 
632
 
        /* Writes Q flag */
633
 
        regs->uregs[rd] = insnslot_1arg_rwflags(rmv, &regs->ARM_cpsr, i_fn);
634
 
}
635
 
 
636
 
static void __kprobes emulate_sel(struct kprobe *p, struct pt_regs *regs)
637
 
{
638
 
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
639
 
        kprobe_opcode_t insn = p->opcode;
640
 
        int rd = (insn >> 12) & 0xf;
641
 
        int rn = (insn >> 16) & 0xf;
642
 
        int rm = insn & 0xf;
643
 
        long rnv = regs->uregs[rn];
644
 
        long rmv = regs->uregs[rm];
645
 
 
646
 
        /* Reads GE bits */
647
 
        regs->uregs[rd] = insnslot_2arg_rflags(rnv, rmv, regs->ARM_cpsr, i_fn);
648
 
}
649
 
 
650
 
static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
651
 
{
652
 
        insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
653
 
 
654
 
        insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
655
 
}
656
 
 
657
 
static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
658
 
{
659
 
}
660
 
 
661
 
static void __kprobes
662
 
emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
663
 
{
664
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
665
 
        kprobe_opcode_t insn = p->opcode;
666
 
        int rd = (insn >> 12) & 0xf;
667
 
        long rdv = regs->uregs[rd];
668
 
 
669
 
        regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
670
 
}
671
 
 
672
 
static void __kprobes
673
 
emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
674
 
{
675
 
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
676
 
        kprobe_opcode_t insn = p->opcode;
677
 
        int rd = (insn >> 12) & 0xf;
678
 
        int rn = insn & 0xf;
679
 
        long rdv = regs->uregs[rd];
680
 
        long rnv = regs->uregs[rn];
681
 
 
682
 
        regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
683
 
}
684
 
 
685
 
static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
686
 
{
687
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
688
 
        kprobe_opcode_t insn = p->opcode;
689
 
        int rd = (insn >> 12) & 0xf;
690
 
        int rm = insn & 0xf;
691
 
        long rmv = regs->uregs[rm];
692
 
 
693
 
        regs->uregs[rd] = insnslot_1arg_rflags(rmv, regs->ARM_cpsr, i_fn);
694
 
}
695
 
 
696
 
static void __kprobes
697
 
emulate_rd12rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
698
 
{
699
 
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
700
 
        kprobe_opcode_t insn = p->opcode;
701
 
        int rd = (insn >> 12) & 0xf;
702
 
        int rn = (insn >> 16) & 0xf;
703
 
        int rm = insn & 0xf;
704
 
        long rnv = regs->uregs[rn];
705
 
        long rmv = regs->uregs[rm];
706
 
 
707
 
        regs->uregs[rd] =
708
 
                insnslot_2arg_rwflags(rnv, rmv, &regs->ARM_cpsr, i_fn);
709
 
}
710
 
 
711
 
static void __kprobes
712
 
emulate_rd16rn12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
713
 
{
714
 
        insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
715
 
        kprobe_opcode_t insn = p->opcode;
716
 
        int rd = (insn >> 16) & 0xf;
717
 
        int rn = (insn >> 12) & 0xf;
718
 
        int rs = (insn >> 8) & 0xf;
719
 
        int rm = insn & 0xf;
720
 
        long rnv = regs->uregs[rn];
721
 
        long rsv = regs->uregs[rs];
722
 
        long rmv = regs->uregs[rm];
723
 
 
724
 
        regs->uregs[rd] =
725
 
                insnslot_3arg_rwflags(rnv, rsv, rmv, &regs->ARM_cpsr, i_fn);
726
 
}
727
 
 
728
 
static void __kprobes
729
 
emulate_rd16rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
730
 
{
731
 
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
732
 
        kprobe_opcode_t insn = p->opcode;
733
 
        int rd = (insn >> 16) & 0xf;
734
 
        int rs = (insn >> 8) & 0xf;
735
 
        int rm = insn & 0xf;
736
 
        long rsv = regs->uregs[rs];
737
 
        long rmv = regs->uregs[rm];
738
 
 
739
 
        regs->uregs[rd] =
740
 
                insnslot_2arg_rwflags(rsv, rmv, &regs->ARM_cpsr, i_fn);
741
 
}
742
 
 
743
 
static void __kprobes
744
 
emulate_rdhi16rdlo12rs8rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
745
 
{
746
 
        insn_llret_4arg_fn_t *i_fn = (insn_llret_4arg_fn_t *)&p->ainsn.insn[0];
747
 
        kprobe_opcode_t insn = p->opcode;
748
 
        union reg_pair fnr;
749
 
        int rdhi = (insn >> 16) & 0xf;
750
 
        int rdlo = (insn >> 12) & 0xf;
751
 
        int rs   = (insn >> 8) & 0xf;
752
 
        int rm   = insn & 0xf;
753
 
        long rsv = regs->uregs[rs];
754
 
        long rmv = regs->uregs[rm];
755
 
 
756
 
        fnr.dr = insnslot_llret_4arg_rwflags(regs->uregs[rdhi],
757
 
                                             regs->uregs[rdlo], rsv, rmv,
758
 
                                             &regs->ARM_cpsr, i_fn);
759
 
        regs->uregs[rdhi] = fnr.r0;
760
 
        regs->uregs[rdlo] = fnr.r1;
761
 
}
762
 
 
763
 
static void __kprobes
764
 
emulate_alu_imm_rflags(struct kprobe *p, struct pt_regs *regs)
765
 
{
766
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
767
 
        kprobe_opcode_t insn = p->opcode;
768
 
        int rd = (insn >> 12) & 0xf;
769
 
        int rn = (insn >> 16) & 0xf;
770
 
        long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
771
 
 
772
 
        regs->uregs[rd] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
773
 
}
774
 
 
775
 
static void __kprobes
776
 
emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
777
 
{
778
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
779
 
        kprobe_opcode_t insn = p->opcode;
780
 
        int rd = (insn >> 12) & 0xf;
781
 
        int rn = (insn >> 16) & 0xf;
782
 
        long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
783
 
 
784
 
        regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
785
 
}
786
 
 
787
 
static void __kprobes
788
 
emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
789
 
{
790
 
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
791
 
        kprobe_opcode_t insn = p->opcode;
792
 
        int rn = (insn >> 16) & 0xf;
793
 
        long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
794
 
 
795
 
        insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
796
 
}
797
 
 
798
 
static void __kprobes
799
 
emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
800
 
{
801
 
        insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
802
 
        kprobe_opcode_t insn = p->opcode;
803
 
        long ppc = (long)p->addr + 8;
804
 
        int rd = (insn >> 12) & 0xf;
805
 
        int rn = (insn >> 16) & 0xf;    /* rn/rnv/rs/rsv may be */
806
 
        int rs = (insn >> 8) & 0xf;     /* invalid, don't care. */
807
 
        int rm = insn & 0xf;
808
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
809
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
810
 
        long rsv = regs->uregs[rs];
811
 
 
812
 
        regs->uregs[rd] =
813
 
                insnslot_3arg_rflags(rnv, rmv, rsv, regs->ARM_cpsr, i_fn);
814
 
}
815
 
 
816
 
static void __kprobes
817
 
emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
818
 
{
819
 
        insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
820
 
        kprobe_opcode_t insn = p->opcode;
821
 
        long ppc = (long)p->addr + 8;
822
 
        int rd = (insn >> 12) & 0xf;
823
 
        int rn = (insn >> 16) & 0xf;    /* rn/rnv/rs/rsv may be */
824
 
        int rs = (insn >> 8) & 0xf;     /* invalid, don't care. */
825
 
        int rm = insn & 0xf;
826
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
827
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
828
 
        long rsv = regs->uregs[rs];
829
 
 
830
 
        regs->uregs[rd] =
831
 
                insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
832
 
}
833
 
 
834
 
static void __kprobes
835
 
emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
836
 
{
837
 
        insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
838
 
        kprobe_opcode_t insn = p->opcode;
839
 
        long ppc = (long)p->addr + 8;
840
 
        int rn = (insn >> 16) & 0xf;
841
 
        int rs = (insn >> 8) & 0xf;     /* rs/rsv may be invalid, don't care. */
842
 
        int rm = insn & 0xf;
843
 
        long rnv = (rn == 15) ? ppc : regs->uregs[rn];
844
 
        long rmv = (rm == 15) ? ppc : regs->uregs[rm];
845
 
        long rsv = regs->uregs[rs];
846
 
 
847
 
        insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
848
 
}
849
 
 
850
 
static enum kprobe_insn __kprobes
851
 
prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
852
 
{
853
 
        int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
854
 
                                         : (~insn & (1 << 22));
855
 
 
856
 
        if (is_writeback(insn) && is_r15(insn, 16))
857
 
                return INSN_REJECTED;   /* Writeback to PC */
858
 
 
859
 
        insn &= 0xfff00fff;
860
 
        insn |= 0x00001000;     /* Rn = r0, Rd = r1 */
861
 
        if (not_imm) {
862
 
                insn &= ~0xf;
863
 
                insn |= 2;      /* Rm = r2 */
864
 
        }
865
 
        asi->insn[0] = insn;
866
 
        asi->insn_handler = (insn & (1 << 20)) ? emulate_ldr : emulate_str;
867
 
        return INSN_GOOD;
868
 
}
869
 
 
870
 
static enum kprobe_insn __kprobes
871
 
prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
872
 
{
873
 
        if (is_r15(insn, 12))
874
 
                return INSN_REJECTED;   /* Rd is PC */
875
 
 
876
 
        insn &= 0xffff0fff;     /* Rd = r0 */
877
 
        asi->insn[0] = insn;
878
 
        asi->insn_handler = emulate_rd12_modify;
879
 
        return INSN_GOOD;
880
 
}
881
 
 
882
 
static enum kprobe_insn __kprobes
883
 
prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
884
 
                            struct arch_specific_insn *asi)
885
 
{
886
 
        if (is_r15(insn, 12))
887
 
                return INSN_REJECTED;   /* Rd is PC */
888
 
 
889
 
        insn &= 0xffff0ff0;     /* Rd = r0 */
890
 
        insn |= 0x00000001;     /* Rn = r1 */
891
 
        asi->insn[0] = insn;
892
 
        asi->insn_handler = emulate_rd12rn0_modify;
893
 
        return INSN_GOOD;
894
 
}
895
 
 
896
 
static enum kprobe_insn __kprobes
897
 
prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
898
 
{
899
 
        if (is_r15(insn, 12))
900
 
                return INSN_REJECTED;   /* Rd is PC */
901
 
 
902
 
        insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
903
 
        asi->insn[0] = insn;
904
 
        asi->insn_handler = emulate_rd12rm0;
905
 
        return INSN_GOOD;
906
 
}
907
 
 
908
 
static enum kprobe_insn __kprobes
909
 
prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
910
 
                                struct arch_specific_insn *asi)
911
 
{
912
 
        if (is_r15(insn, 12))
913
 
                return INSN_REJECTED;   /* Rd is PC */
914
 
 
915
 
        insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
916
 
        insn |= 0x00000001;     /* Rm = r1 */
917
 
        asi->insn[0] = insn;
918
 
        asi->insn_handler = emulate_rd12rn16rm0_rwflags;
919
 
        return INSN_GOOD;
920
 
}
921
 
 
922
 
static enum kprobe_insn __kprobes
923
 
prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
924
 
                               struct arch_specific_insn *asi)
925
 
{
926
 
        if (is_r15(insn, 16))
927
 
                return INSN_REJECTED;   /* Rd is PC */
928
 
 
929
 
        insn &= 0xfff0f0f0;     /* Rd = r0, Rs = r0 */
930
 
        insn |= 0x00000001;     /* Rm = r1          */
931
 
        asi->insn[0] = insn;
932
 
        asi->insn_handler = emulate_rd16rs8rm0_rwflags;
933
 
        return INSN_GOOD;
934
 
}
935
 
 
936
 
static enum kprobe_insn __kprobes
937
 
prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
938
 
                                   struct arch_specific_insn *asi)
939
 
{
940
 
        if (is_r15(insn, 16))
941
 
                return INSN_REJECTED;   /* Rd is PC */
942
 
 
943
 
        insn &= 0xfff000f0;     /* Rd = r0, Rn = r0 */
944
 
        insn |= 0x00000102;     /* Rs = r1, Rm = r2 */
945
 
        asi->insn[0] = insn;
946
 
        asi->insn_handler = emulate_rd16rn12rs8rm0_rwflags;
947
 
        return INSN_GOOD;
948
 
}
949
 
 
950
 
static enum kprobe_insn __kprobes
951
 
prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
952
 
                                       struct arch_specific_insn *asi)
953
 
{
954
 
        if (is_r15(insn, 16) || is_r15(insn, 12))
955
 
                return INSN_REJECTED;   /* RdHi or RdLo is PC */
956
 
 
957
 
        insn &= 0xfff000f0;     /* RdHi = r0, RdLo = r1 */
958
 
        insn |= 0x00001203;     /* Rs = r2, Rm = r3 */
959
 
        asi->insn[0] = insn;
960
 
        asi->insn_handler = emulate_rdhi16rdlo12rs8rm0_rwflags;
961
 
        return INSN_GOOD;
962
 
}
963
 
 
964
 
/*
965
 
 * For the instruction masking and comparisons in all the "space_*"
966
 
 * functions below, Do _not_ rearrange the order of tests unless
967
 
 * you're very, very sure of what you are doing.  For the sake of
968
 
 * efficiency, the masks for some tests sometimes assume other test
969
 
 * have been done prior to them so the number of patterns to test
970
 
 * for an instruction set can be as broad as possible to reduce the
971
 
 * number of tests needed.
972
 
 */
973
 
 
974
 
static enum kprobe_insn __kprobes
975
 
space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
976
 
{
977
 
        /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
978
 
        /* PLDI        : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
979
 
        /* PLDW        : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
980
 
        /* PLD         : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
981
 
        if ((insn & 0xfe300000) == 0xf4100000) {
982
 
                asi->insn_handler = emulate_nop;
983
 
                return INSN_GOOD_NO_SLOT;
984
 
        }
985
 
 
986
 
        /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
987
 
        if ((insn & 0xfe000000) == 0xfa000000) {
988
 
                asi->insn_handler = simulate_blx1;
989
 
                return INSN_GOOD_NO_SLOT;
990
 
        }
991
 
 
992
 
        /* CPS   : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
993
 
        /* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
994
 
 
995
 
        /* SRS   : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
996
 
        /* RFE   : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
997
 
 
998
 
        /* Coprocessor instructions... */
999
 
        /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1000
 
        /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1001
 
        /* LDC2  : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1002
 
        /* STC2  : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1003
 
        /* CDP2  : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1004
 
        /* MCR2  : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1005
 
        /* MRC2  : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1006
 
 
1007
 
        return INSN_REJECTED;
1008
 
}
1009
 
 
1010
 
static enum kprobe_insn __kprobes
1011
 
space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1012
 
{
1013
 
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
1014
 
        if ((insn & 0x0f900010) == 0x01000000) {
1015
 
 
1016
 
                /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
1017
 
                if ((insn & 0x0ff000f0) == 0x01000000) {
1018
 
                        if (is_r15(insn, 12))
1019
 
                                return INSN_REJECTED;   /* Rd is PC */
1020
 
                        asi->insn_handler = simulate_mrs;
1021
 
                        return INSN_GOOD_NO_SLOT;
1022
 
                }
1023
 
 
1024
 
                /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
1025
 
                if ((insn & 0x0ff00090) == 0x01400080)
1026
 
                        return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
1027
 
                                                                        asi);
1028
 
 
1029
 
                /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
1030
 
                /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
1031
 
                if ((insn & 0x0ff000b0) == 0x012000a0 ||
1032
 
                    (insn & 0x0ff00090) == 0x01600080)
1033
 
                        return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1034
 
 
1035
 
                /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
1036
 
                /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
1037
 
                if ((insn & 0x0ff00090) == 0x01000080 ||
1038
 
                    (insn & 0x0ff000b0) == 0x01200080)
1039
 
                        return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1040
 
 
1041
 
                /* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
1042
 
                /* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
1043
 
                /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
1044
 
 
1045
 
                /* Other instruction encodings aren't yet defined */
1046
 
                return INSN_REJECTED;
1047
 
        }
1048
 
 
1049
 
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
1050
 
        else if ((insn & 0x0f900090) == 0x01000010) {
1051
 
 
1052
 
                /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
1053
 
                /* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
1054
 
                if ((insn & 0x0ff000d0) == 0x01200010) {
1055
 
                        if ((insn & 0x0ff000ff) == 0x0120003f)
1056
 
                                return INSN_REJECTED; /* BLX pc */
1057
 
                        asi->insn_handler = simulate_blx2bx;
1058
 
                        return INSN_GOOD_NO_SLOT;
1059
 
                }
1060
 
 
1061
 
                /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
1062
 
                if ((insn & 0x0ff000f0) == 0x01600010)
1063
 
                        return prep_emulate_rd12rm0(insn, asi);
1064
 
 
1065
 
                /* QADD    : cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx :Q */
1066
 
                /* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
1067
 
                /* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
1068
 
                /* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
1069
 
                if ((insn & 0x0f9000f0) == 0x01000050)
1070
 
                        return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1071
 
 
1072
 
                /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
1073
 
                /* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
1074
 
 
1075
 
                /* Other instruction encodings aren't yet defined */
1076
 
                return INSN_REJECTED;
1077
 
        }
1078
 
 
1079
 
        /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
1080
 
        else if ((insn & 0x0f0000f0) == 0x00000090) {
1081
 
 
1082
 
                /* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
1083
 
                /* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
1084
 
                /* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
1085
 
                /* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
1086
 
                /* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
1087
 
                /* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
1088
 
                /* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
1089
 
                /* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
1090
 
                /* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
1091
 
                /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
1092
 
                /* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
1093
 
                /* UMLALS : cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx :cc */
1094
 
                /* SMULL  : cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx :   */
1095
 
                /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
1096
 
                /* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
1097
 
                /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
1098
 
                if ((insn & 0x00d00000) == 0x00500000)
1099
 
                        return INSN_REJECTED;
1100
 
                else if ((insn & 0x00e00000) == 0x00000000)
1101
 
                        return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1102
 
                else if ((insn & 0x00a00000) == 0x00200000)
1103
 
                        return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1104
 
                else
1105
 
                        return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
1106
 
                                                                        asi);
1107
 
        }
1108
 
 
1109
 
        /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
1110
 
        else if ((insn & 0x0e000090) == 0x00000090) {
1111
 
 
1112
 
                /* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
1113
 
                /* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
1114
 
                /* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
1115
 
                /* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
1116
 
                /* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
1117
 
                /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
1118
 
                /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
1119
 
                /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
1120
 
                /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
1121
 
                /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
1122
 
                /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
1123
 
                /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
1124
 
                /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
1125
 
 
1126
 
                /* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
1127
 
                /* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
1128
 
                /* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
1129
 
                /* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
1130
 
                /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
1131
 
                /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
1132
 
                if ((insn & 0x0f0000f0) == 0x01000090) {
1133
 
                        if ((insn & 0x0fb000f0) == 0x01000090) {
1134
 
                                /* SWP/SWPB */
1135
 
                                return prep_emulate_rd12rn16rm0_wflags(insn,
1136
 
                                                                        asi);
1137
 
                        } else {
1138
 
                                /* STREX/LDREX variants and unallocaed space */
1139
 
                                return INSN_REJECTED;
1140
 
                        }
1141
 
 
1142
 
                } else if ((insn & 0x0e1000d0) == 0x00000d0) {
1143
 
                        /* STRD/LDRD */
1144
 
                        if ((insn & 0x0000e000) == 0x0000e000)
1145
 
                                return INSN_REJECTED;   /* Rd is LR or PC */
1146
 
                        if (is_writeback(insn) && is_r15(insn, 16))
1147
 
                                return INSN_REJECTED;   /* Writeback to PC */
1148
 
 
1149
 
                        insn &= 0xfff00fff;
1150
 
                        insn |= 0x00002000;     /* Rn = r0, Rd = r2 */
1151
 
                        if (!(insn & (1 << 22))) {
1152
 
                                /* Register index */
1153
 
                                insn &= ~0xf;
1154
 
                                insn |= 1;      /* Rm = r1 */
1155
 
                        }
1156
 
                        asi->insn[0] = insn;
1157
 
                        asi->insn_handler =
1158
 
                                (insn & (1 << 5)) ? emulate_strd : emulate_ldrd;
1159
 
                        return INSN_GOOD;
1160
 
                }
1161
 
 
1162
 
                /* LDRH/STRH/LDRSB/LDRSH */
1163
 
                if (is_r15(insn, 12))
1164
 
                        return INSN_REJECTED;   /* Rd is PC */
1165
 
                return prep_emulate_ldr_str(insn, asi);
1166
 
        }
1167
 
 
1168
 
        /* cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx xxxx */
1169
 
 
1170
 
        /*
1171
 
         * ALU op with S bit and Rd == 15 :
1172
 
         *      cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
1173
 
         */
1174
 
        if ((insn & 0x0e10f000) == 0x0010f000)
1175
 
                return INSN_REJECTED;
1176
 
 
1177
 
        /*
1178
 
         * "mov ip, sp" is the most common kprobe'd instruction by far.
1179
 
         * Check and optimize for it explicitly.
1180
 
         */
1181
 
        if (insn == 0xe1a0c00d) {
1182
 
                asi->insn_handler = simulate_mov_ipsp;
1183
 
                return INSN_GOOD_NO_SLOT;
1184
 
        }
1185
 
 
1186
 
        /*
1187
 
         * Data processing: Immediate-shift / Register-shift
1188
 
         * ALU op : cccc 000x xxxx xxxx xxxx xxxx xxxx xxxx
1189
 
         * CPY    : cccc 0001 1010 xxxx xxxx 0000 0000 xxxx
1190
 
         * MOV    : cccc 0001 101x xxxx xxxx xxxx xxxx xxxx
1191
 
         * *S (bit 20) updates condition codes
1192
 
         * ADC/SBC/RSC reads the C flag
1193
 
         */
1194
 
        insn &= 0xfff00ff0;     /* Rn = r0, Rd = r0 */
1195
 
        insn |= 0x00000001;     /* Rm = r1 */
1196
 
        if (insn & 0x010) {
1197
 
                insn &= 0xfffff0ff;     /* register shift */
1198
 
                insn |= 0x00000200;     /* Rs = r2 */
1199
 
        }
1200
 
        asi->insn[0] = insn;
1201
 
 
1202
 
        if ((insn & 0x0f900000) == 0x01100000) {
1203
 
                /*
1204
 
                 * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
1205
 
                 * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
1206
 
                 * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
1207
 
                 * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
1208
 
                 */
1209
 
                asi->insn_handler = emulate_alu_tests;
1210
 
        } else {
1211
 
                /* ALU ops which write to Rd */
1212
 
                asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
1213
 
                                emulate_alu_rwflags : emulate_alu_rflags;
1214
 
        }
1215
 
        return INSN_GOOD;
1216
 
}
1217
 
 
1218
 
static enum kprobe_insn __kprobes
1219
 
space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1220
 
{
1221
 
        /* MOVW  : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
1222
 
        /* MOVT  : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
1223
 
        if ((insn & 0x0fb00000) == 0x03000000)
1224
 
                return prep_emulate_rd12_modify(insn, asi);
1225
 
 
1226
 
        /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
1227
 
        if ((insn & 0x0fff0000) == 0x03200000) {
1228
 
                unsigned op2 = insn & 0x000000ff;
1229
 
                if (op2 == 0x01 || op2 == 0x04) {
1230
 
                        /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
1231
 
                        /* SEV   : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
1232
 
                        asi->insn[0] = insn;
1233
 
                        asi->insn_handler = emulate_none;
1234
 
                        return INSN_GOOD;
1235
 
                } else if (op2 <= 0x03) {
1236
 
                        /* NOP   : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
1237
 
                        /* WFE   : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
1238
 
                        /* WFI   : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
1239
 
                        /*
1240
 
                         * We make WFE and WFI true NOPs to avoid stalls due
1241
 
                         * to missing events whilst processing the probe.
1242
 
                         */
1243
 
                        asi->insn_handler = emulate_nop;
1244
 
                        return INSN_GOOD_NO_SLOT;
1245
 
                }
1246
 
                /* For DBG and unallocated hints it's safest to reject them */
1247
 
                return INSN_REJECTED;
1248
 
        }
1249
 
 
1250
 
        /*
1251
 
         * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
1252
 
         * ALU op with S bit and Rd == 15 :
1253
 
         *         cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
1254
 
         */
1255
 
        if ((insn & 0x0fb00000) == 0x03200000 ||        /* MSR */
1256
 
            (insn & 0x0e10f000) == 0x0210f000)          /* ALU s-bit, R15  */
1257
 
                return INSN_REJECTED;
1258
 
 
1259
 
        /*
1260
 
         * Data processing: 32-bit Immediate
1261
 
         * ALU op : cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx
1262
 
         * MOV    : cccc 0011 101x xxxx xxxx xxxx xxxx xxxx
1263
 
         * *S (bit 20) updates condition codes
1264
 
         * ADC/SBC/RSC reads the C flag
1265
 
         */
1266
 
        insn &= 0xfff00fff;     /* Rn = r0 and Rd = r0 */
1267
 
        asi->insn[0] = insn;
1268
 
 
1269
 
        if ((insn & 0x0f900000) == 0x03100000) {
1270
 
                /*
1271
 
                 * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
1272
 
                 * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
1273
 
                 * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
1274
 
                 * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
1275
 
                 */
1276
 
                asi->insn_handler = emulate_alu_tests_imm;
1277
 
        } else {
1278
 
                /* ALU ops which write to Rd */
1279
 
                asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
1280
 
                        emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
1281
 
        }
1282
 
        return INSN_GOOD;
1283
 
}
1284
 
 
1285
 
static enum kprobe_insn __kprobes
1286
 
space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1287
 
{
1288
 
        /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
1289
 
        if ((insn & 0x0ff000f0) == 0x068000b0) {
1290
 
                if (is_r15(insn, 12))
1291
 
                        return INSN_REJECTED;   /* Rd is PC */
1292
 
                insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
1293
 
                insn |= 0x00000001;     /* Rm = r1 */
1294
 
                asi->insn[0] = insn;
1295
 
                asi->insn_handler = emulate_sel;
1296
 
                return INSN_GOOD;
1297
 
        }
1298
 
 
1299
 
        /* SSAT   : cccc 0110 101x xxxx xxxx xxxx xx01 xxxx :Q */
1300
 
        /* USAT   : cccc 0110 111x xxxx xxxx xxxx xx01 xxxx :Q */
1301
 
        /* SSAT16 : cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx :Q */
1302
 
        /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
1303
 
        if ((insn & 0x0fa00030) == 0x06a00010 ||
1304
 
            (insn & 0x0fb000f0) == 0x06a00030) {
1305
 
                if (is_r15(insn, 12))
1306
 
                        return INSN_REJECTED;   /* Rd is PC */
1307
 
                insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
1308
 
                asi->insn[0] = insn;
1309
 
                asi->insn_handler = emulate_sat;
1310
 
                return INSN_GOOD;
1311
 
        }
1312
 
 
1313
 
        /* REV    : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
1314
 
        /* REV16  : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
1315
 
        /* RBIT   : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
1316
 
        /* REVSH  : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
1317
 
        if ((insn & 0x0ff00070) == 0x06b00030 ||
1318
 
            (insn & 0x0ff00070) == 0x06f00030)
1319
 
                return prep_emulate_rd12rm0(insn, asi);
1320
 
 
1321
 
        /* ???       : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx :   */
1322
 
        /* SADD16    : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
1323
 
        /* SADDSUBX  : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
1324
 
        /* SSUBADDX  : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
1325
 
        /* SSUB16    : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
1326
 
        /* SADD8     : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
1327
 
        /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx :   */
1328
 
        /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx :   */
1329
 
        /* SSUB8     : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
1330
 
        /* QADD16    : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx :   */
1331
 
        /* QADDSUBX  : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx :   */
1332
 
        /* QSUBADDX  : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx :   */
1333
 
        /* QSUB16    : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx :   */
1334
 
        /* QADD8     : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx :   */
1335
 
        /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx :   */
1336
 
        /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx :   */
1337
 
        /* QSUB8     : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx :   */
1338
 
        /* SHADD16   : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx :   */
1339
 
        /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx :   */
1340
 
        /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx :   */
1341
 
        /* SHSUB16   : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx :   */
1342
 
        /* SHADD8    : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx :   */
1343
 
        /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx :   */
1344
 
        /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx :   */
1345
 
        /* SHSUB8    : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx :   */
1346
 
        /* ???       : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx :   */
1347
 
        /* UADD16    : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
1348
 
        /* UADDSUBX  : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
1349
 
        /* USUBADDX  : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
1350
 
        /* USUB16    : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
1351
 
        /* UADD8     : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
1352
 
        /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx :   */
1353
 
        /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx :   */
1354
 
        /* USUB8     : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
1355
 
        /* UQADD16   : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx :   */
1356
 
        /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx :   */
1357
 
        /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx :   */
1358
 
        /* UQSUB16   : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx :   */
1359
 
        /* UQADD8    : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx :   */
1360
 
        /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx :   */
1361
 
        /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx :   */
1362
 
        /* UQSUB8    : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx :   */
1363
 
        /* UHADD16   : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx :   */
1364
 
        /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx :   */
1365
 
        /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx :   */
1366
 
        /* UHSUB16   : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx :   */
1367
 
        /* UHADD8    : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx :   */
1368
 
        /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx :   */
1369
 
        /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx :   */
1370
 
        /* UHSUB8    : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx :   */
1371
 
        if ((insn & 0x0f800010) == 0x06000010) {
1372
 
                if ((insn & 0x00300000) == 0x00000000 ||
1373
 
                    (insn & 0x000000e0) == 0x000000a0 ||
1374
 
                    (insn & 0x000000e0) == 0x000000c0)
1375
 
                        return INSN_REJECTED;   /* Unallocated space */
1376
 
                return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1377
 
        }
1378
 
 
1379
 
        /* PKHBT     : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx :   */
1380
 
        /* PKHTB     : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx :   */
1381
 
        if ((insn & 0x0ff00030) == 0x06800010)
1382
 
                return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1383
 
 
1384
 
        /* SXTAB16   : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx :   */
1385
 
        /* SXTB16    : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx :   */
1386
 
        /* ???       : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx :   */
1387
 
        /* SXTAB     : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
1388
 
        /* SXTB      : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx :   */
1389
 
        /* SXTAH     : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx :   */
1390
 
        /* SXTH      : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx :   */
1391
 
        /* UXTAB16   : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx :   */
1392
 
        /* UXTB16    : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx :   */
1393
 
        /* ???       : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx :   */
1394
 
        /* UXTAB     : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx :   */
1395
 
        /* UXTB      : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx :   */
1396
 
        /* UXTAH     : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx :   */
1397
 
        /* UXTH      : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx :   */
1398
 
        if ((insn & 0x0f8000f0) == 0x06800070) {
1399
 
                if ((insn & 0x00300000) == 0x00100000)
1400
 
                        return INSN_REJECTED;   /* Unallocated space */
1401
 
 
1402
 
                if ((insn & 0x000f0000) == 0x000f0000)
1403
 
                        return prep_emulate_rd12rm0(insn, asi);
1404
 
                else
1405
 
                        return prep_emulate_rd12rn16rm0_wflags(insn, asi);
1406
 
        }
1407
 
 
1408
 
        /* Other instruction encodings aren't yet defined */
1409
 
        return INSN_REJECTED;
1410
 
}
1411
 
 
1412
 
static enum kprobe_insn __kprobes
1413
 
space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1414
 
{
1415
 
        /* Undef : cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */
1416
 
        if ((insn & 0x0ff000f0) == 0x03f000f0)
1417
 
                return INSN_REJECTED;
1418
 
 
1419
 
        /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
1420
 
        /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
1421
 
        if ((insn & 0x0ff00090) == 0x07400010)
1422
 
                return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
1423
 
 
1424
 
        /* SMLAD  : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
1425
 
        /* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
1426
 
        /* SMLSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
1427
 
        /* SMUSD  : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx :  */
1428
 
        /* SMMLA  : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx :  */
1429
 
        /* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
1430
 
        /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx :  */
1431
 
        /* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx :  */
1432
 
        if ((insn & 0x0ff00090) == 0x07000010 ||
1433
 
            (insn & 0x0ff000d0) == 0x07500010 ||
1434
 
            (insn & 0x0ff000f0) == 0x07800010) {
1435
 
 
1436
 
                if ((insn & 0x0000f000) == 0x0000f000)
1437
 
                        return prep_emulate_rd16rs8rm0_wflags(insn, asi);
1438
 
                else
1439
 
                        return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1440
 
        }
1441
 
 
1442
 
        /* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
1443
 
        if ((insn & 0x0ff000d0) == 0x075000d0)
1444
 
                return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
1445
 
 
1446
 
        /* SBFX   : cccc 0111 101x xxxx xxxx xxxx x101 xxxx :  */
1447
 
        /* UBFX   : cccc 0111 111x xxxx xxxx xxxx x101 xxxx :  */
1448
 
        if ((insn & 0x0fa00070) == 0x07a00050)
1449
 
                return prep_emulate_rd12rm0(insn, asi);
1450
 
 
1451
 
        /* BFI    : cccc 0111 110x xxxx xxxx xxxx x001 xxxx :  */
1452
 
        /* BFC    : cccc 0111 110x xxxx xxxx xxxx x001 1111 :  */
1453
 
        if ((insn & 0x0fe00070) == 0x07c00010) {
1454
 
 
1455
 
                if ((insn & 0x0000000f) == 0x0000000f)
1456
 
                        return prep_emulate_rd12_modify(insn, asi);
1457
 
                else
1458
 
                        return prep_emulate_rd12rn0_modify(insn, asi);
1459
 
        }
1460
 
 
1461
 
        return INSN_REJECTED;
1462
 
}
1463
 
 
1464
 
static enum kprobe_insn __kprobes
1465
 
space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1466
 
{
1467
 
        /* LDR   : cccc 01xx x0x1 xxxx xxxx xxxx xxxx xxxx */
1468
 
        /* LDRB  : cccc 01xx x1x1 xxxx xxxx xxxx xxxx xxxx */
1469
 
        /* LDRBT : cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */
1470
 
        /* LDRT  : cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */
1471
 
        /* STR   : cccc 01xx x0x0 xxxx xxxx xxxx xxxx xxxx */
1472
 
        /* STRB  : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
1473
 
        /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
1474
 
        /* STRT  : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
1475
 
 
1476
 
        if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
1477
 
                return INSN_REJECTED;   /* LDRB into PC */
1478
 
 
1479
 
        return prep_emulate_ldr_str(insn, asi);
1480
 
}
1481
 
 
1482
 
static enum kprobe_insn __kprobes
1483
 
space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1484
 
{
1485
 
        /* LDM(2) : cccc 100x x101 xxxx 0xxx xxxx xxxx xxxx */
1486
 
        /* LDM(3) : cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */
1487
 
        if ((insn & 0x0e708000) == 0x85000000 ||
1488
 
            (insn & 0x0e508000) == 0x85010000)
1489
 
                return INSN_REJECTED;
1490
 
 
1491
 
        /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
1492
 
        /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
1493
 
        asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
1494
 
                                simulate_stm1_pc : simulate_ldm1stm1;
1495
 
        return INSN_GOOD_NO_SLOT;
1496
 
}
1497
 
 
1498
 
static enum kprobe_insn __kprobes
1499
 
space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1500
 
{
1501
 
        /* B  : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
1502
 
        /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
1503
 
        asi->insn_handler = simulate_bbl;
1504
 
        return INSN_GOOD_NO_SLOT;
1505
 
}
1506
 
 
1507
 
static enum kprobe_insn __kprobes
1508
 
space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1509
 
{
1510
 
        /* Coprocessor instructions... */
1511
 
        /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1512
 
        /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1513
 
        /* LDC  : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1514
 
        /* STC  : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1515
 
        /* CDP  : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1516
 
        /* MCR  : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1517
 
        /* MRC  : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1518
 
 
1519
 
        /* SVC  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
1520
 
 
1521
 
        return INSN_REJECTED;
1522
 
}
1523
 
 
1524
 
static unsigned long __kprobes __check_eq(unsigned long cpsr)
1525
 
{
1526
 
        return cpsr & PSR_Z_BIT;
1527
 
}
1528
 
 
1529
 
static unsigned long __kprobes __check_ne(unsigned long cpsr)
1530
 
{
1531
 
        return (~cpsr) & PSR_Z_BIT;
1532
 
}
1533
 
 
1534
 
static unsigned long __kprobes __check_cs(unsigned long cpsr)
1535
 
{
1536
 
        return cpsr & PSR_C_BIT;
1537
 
}
1538
 
 
1539
 
static unsigned long __kprobes __check_cc(unsigned long cpsr)
1540
 
{
1541
 
        return (~cpsr) & PSR_C_BIT;
1542
 
}
1543
 
 
1544
 
static unsigned long __kprobes __check_mi(unsigned long cpsr)
1545
 
{
1546
 
        return cpsr & PSR_N_BIT;
1547
 
}
1548
 
 
1549
 
static unsigned long __kprobes __check_pl(unsigned long cpsr)
1550
 
{
1551
 
        return (~cpsr) & PSR_N_BIT;
1552
 
}
1553
 
 
1554
 
static unsigned long __kprobes __check_vs(unsigned long cpsr)
1555
 
{
1556
 
        return cpsr & PSR_V_BIT;
1557
 
}
1558
 
 
1559
 
static unsigned long __kprobes __check_vc(unsigned long cpsr)
1560
 
{
1561
 
        return (~cpsr) & PSR_V_BIT;
1562
 
}
1563
 
 
1564
 
static unsigned long __kprobes __check_hi(unsigned long cpsr)
1565
 
{
1566
 
        cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
1567
 
        return cpsr & PSR_C_BIT;
1568
 
}
1569
 
 
1570
 
static unsigned long __kprobes __check_ls(unsigned long cpsr)
1571
 
{
1572
 
        cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
1573
 
        return (~cpsr) & PSR_C_BIT;
1574
 
}
1575
 
 
1576
 
static unsigned long __kprobes __check_ge(unsigned long cpsr)
1577
 
{
1578
 
        cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
1579
 
        return (~cpsr) & PSR_N_BIT;
1580
 
}
1581
 
 
1582
 
static unsigned long __kprobes __check_lt(unsigned long cpsr)
1583
 
{
1584
 
        cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
1585
 
        return cpsr & PSR_N_BIT;
1586
 
}
1587
 
 
1588
 
static unsigned long __kprobes __check_gt(unsigned long cpsr)
1589
 
{
1590
 
        unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
1591
 
        temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
1592
 
        return (~temp) & PSR_N_BIT;
1593
 
}
1594
 
 
1595
 
static unsigned long __kprobes __check_le(unsigned long cpsr)
1596
 
{
1597
 
        unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
1598
 
        temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
1599
 
        return temp & PSR_N_BIT;
1600
 
}
1601
 
 
1602
 
static unsigned long __kprobes __check_al(unsigned long cpsr)
1603
 
{
1604
 
        return true;
1605
 
}
1606
 
 
1607
 
static kprobe_check_cc * const condition_checks[16] = {
1608
 
        &__check_eq, &__check_ne, &__check_cs, &__check_cc,
1609
 
        &__check_mi, &__check_pl, &__check_vs, &__check_vc,
1610
 
        &__check_hi, &__check_ls, &__check_ge, &__check_lt,
1611
 
        &__check_gt, &__check_le, &__check_al, &__check_al
1612
 
};
1613
 
 
1614
 
/* Return:
1615
 
 *   INSN_REJECTED     If instruction is one not allowed to kprobe,
1616
 
 *   INSN_GOOD         If instruction is supported and uses instruction slot,
1617
 
 *   INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
1618
 
 *
1619
 
 * For instructions we don't want to kprobe (INSN_REJECTED return result):
1620
 
 *   These are generally ones that modify the processor state making
1621
 
 *   them "hard" to simulate such as switches processor modes or
1622
 
 *   make accesses in alternate modes.  Any of these could be simulated
1623
 
 *   if the work was put into it, but low return considering they
1624
 
 *   should also be very rare.
1625
 
 */
1626
 
enum kprobe_insn __kprobes
1627
 
arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1628
 
{
1629
 
        asi->insn_check_cc = condition_checks[insn>>28];
1630
 
        asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
1631
 
 
1632
 
        if ((insn & 0xf0000000) == 0xf0000000)
1633
 
 
1634
 
                return space_1111(insn, asi);
1635
 
 
1636
 
        else if ((insn & 0x0e000000) == 0x00000000)
1637
 
 
1638
 
                return space_cccc_000x(insn, asi);
1639
 
 
1640
 
        else if ((insn & 0x0e000000) == 0x02000000)
1641
 
 
1642
 
                return space_cccc_001x(insn, asi);
1643
 
 
1644
 
        else if ((insn & 0x0f000010) == 0x06000010)
1645
 
 
1646
 
                return space_cccc_0110__1(insn, asi);
1647
 
 
1648
 
        else if ((insn & 0x0f000010) == 0x07000010)
1649
 
 
1650
 
                return space_cccc_0111__1(insn, asi);
1651
 
 
1652
 
        else if ((insn & 0x0c000000) == 0x04000000)
1653
 
 
1654
 
                return space_cccc_01xx(insn, asi);
1655
 
 
1656
 
        else if ((insn & 0x0e000000) == 0x08000000)
1657
 
 
1658
 
                return space_cccc_100x(insn, asi);
1659
 
 
1660
 
        else if ((insn & 0x0e000000) == 0x0a000000)
1661
 
 
1662
 
                return space_cccc_101x(insn, asi);
1663
 
 
1664
 
        return space_cccc_11xx(insn, asi);
1665
 
}
1666
 
 
1667
 
void __init arm_kprobe_decode_init(void)
1668
 
{
1669
 
        find_str_pc_offset();
1670
 
}