61 #include <linux/kernel.h>
63 #include <linux/module.h>
67 #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
69 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
71 #if __LINUX_ARM_ARCH__ >= 6
72 #define BLX(reg) "blx "reg" \n\t"
74 #define BLX(reg) "mov lr, pc \n\t" \
114 if (insn & (1 << 24))
115 regs->ARM_lr = iaddr + 4;
117 regs->ARM_pc = iaddr + 8 + disp;
126 regs->ARM_lr = iaddr + 4;
127 regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2);
135 long rmv = regs->
uregs[rm];
140 regs->ARM_pc = rmv & ~0x1;
149 int rd = (insn >> 12) & 0xf;
150 unsigned long mask = 0xf8ff03df;
163 unsigned long pc = (
unsigned long)p->
addr + 8;
164 int rt = (insn >> 12) & 0xf;
165 int rn = (insn >> 16) & 0xf;
168 register unsigned long rtv
asm(
"r0") = regs->
uregs[rt];
169 register unsigned long rt2v
asm(
"r1") = regs->
uregs[rt+1];
170 register unsigned long rnv
asm(
"r2") = (rn == 15) ? pc
172 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
176 :
"=r" (rtv),
"=r" (rt2v),
"=r" (rnv)
177 :
"0" (rtv),
"1" (rt2v),
"2" (rnv),
"r" (rmv),
179 :
"lr",
"memory",
"cc"
182 regs->
uregs[rt] = rtv;
183 regs->
uregs[rt+1] = rt2v;
185 regs->
uregs[rn] = rnv;
192 unsigned long pc = (
unsigned long)p->
addr + 8;
193 int rt = (insn >> 12) & 0xf;
194 int rn = (insn >> 16) & 0xf;
197 register unsigned long rtv
asm(
"r0");
198 register unsigned long rnv
asm(
"r2") = (rn == 15) ? pc
200 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
204 :
"=r" (rtv),
"=r" (rnv)
205 :
"1" (rnv),
"r" (rmv), [
fn]
"r" (p->
ainsn.insn_fn)
206 :
"lr",
"memory",
"cc"
210 load_write_pc(rtv, regs);
212 regs->
uregs[rt] = rtv;
215 regs->
uregs[rn] = rnv;
223 unsigned long rnpc = (
unsigned long)p->
addr + 8;
224 int rt = (insn >> 12) & 0xf;
225 int rn = (insn >> 16) & 0xf;
228 register unsigned long rtv
asm(
"r0") = (rt == 15) ? rtpc
230 register unsigned long rnv
asm(
"r2") = (rn == 15) ? rnpc
232 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
237 :
"r" (rtv),
"0" (rnv),
"r" (rmv), [
fn]
"r" (p->
ainsn.insn_fn)
238 :
"lr",
"memory",
"cc"
242 regs->
uregs[rn] = rnv;
246 emulate_rd12rn16rm0rs8_rwflags(
struct kprobe *p,
struct pt_regs *regs)
249 unsigned long pc = (
unsigned long)p->
addr + 8;
250 int rd = (insn >> 12) & 0xf;
251 int rn = (insn >> 16) & 0xf;
253 int rs = (insn >> 8) & 0xf;
255 register unsigned long rdv
asm(
"r0") = regs->
uregs[
rd];
256 register unsigned long rnv
asm(
"r2") = (rn == 15) ? pc
258 register unsigned long rmv
asm(
"r3") = (rm == 15) ? pc
260 register unsigned long rsv asm(
"r1") = regs->
uregs[rs];
261 unsigned long cpsr = regs->ARM_cpsr;
264 "msr cpsr_fs, %[cpsr] \n\t"
266 "mrs %[cpsr], cpsr \n\t"
267 :
"=r" (rdv), [cpsr]
"=r" (cpsr)
268 :
"0" (rdv),
"r" (rnv),
"r" (rmv),
"r" (
rsv),
269 "1" (cpsr), [
fn]
"r" (p->
ainsn.insn_fn)
270 :
"lr",
"memory",
"cc"
274 alu_write_pc(rdv, regs);
281 emulate_rd12rn16rm0_rwflags_nopc(
struct kprobe *p,
struct pt_regs *regs)
284 int rd = (insn >> 12) & 0xf;
285 int rn = (insn >> 16) & 0xf;
288 register unsigned long rdv
asm(
"r0") = regs->
uregs[rd];
289 register unsigned long rnv
asm(
"r2") = regs->
uregs[rn];
290 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
291 unsigned long cpsr = regs->ARM_cpsr;
294 "msr cpsr_fs, %[cpsr] \n\t"
296 "mrs %[cpsr], cpsr \n\t"
297 :
"=r" (rdv), [cpsr]
"=r" (cpsr)
298 :
"0" (rdv),
"r" (rnv),
"r" (rmv),
299 "1" (cpsr), [
fn]
"r" (p->
ainsn.insn_fn)
300 :
"lr",
"memory",
"cc"
308 emulate_rd16rn12rm0rs8_rwflags_nopc(
struct kprobe *p,
struct pt_regs *regs)
311 int rd = (insn >> 16) & 0xf;
312 int rn = (insn >> 12) & 0xf;
314 int rs = (insn >> 8) & 0xf;
316 register unsigned long rdv
asm(
"r2") = regs->
uregs[rd];
317 register unsigned long rnv
asm(
"r0") = regs->
uregs[rn];
318 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
319 register unsigned long rsv asm(
"r1") = regs->
uregs[rs];
320 unsigned long cpsr = regs->ARM_cpsr;
323 "msr cpsr_fs, %[cpsr] \n\t"
325 "mrs %[cpsr], cpsr \n\t"
326 :
"=r" (rdv), [cpsr]
"=r" (cpsr)
327 :
"0" (rdv),
"r" (rnv),
"r" (rmv),
"r" (
rsv),
328 "1" (cpsr), [
fn]
"r" (p->
ainsn.insn_fn)
329 :
"lr",
"memory",
"cc"
337 emulate_rd12rm0_noflags_nopc(
struct kprobe *p,
struct pt_regs *regs)
340 int rd = (insn >> 12) & 0xf;
343 register unsigned long rdv
asm(
"r0") = regs->
uregs[rd];
344 register unsigned long rmv
asm(
"r3") = regs->
uregs[rm];
349 :
"0" (rdv),
"r" (rmv), [
fn]
"r" (p->
ainsn.insn_fn)
350 :
"lr",
"memory",
"cc"
357 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(
struct kprobe *p,
struct pt_regs *regs)
360 int rdlo = (insn >> 12) & 0xf;
361 int rdhi = (insn >> 16) & 0xf;
363 int rm = (insn >> 8) & 0xf;
365 register unsigned long rdlov
asm(
"r0") = regs->
uregs[rdlo];
366 register unsigned long rdhiv
asm(
"r2") = regs->
uregs[rdhi];
367 register unsigned long rnv
asm(
"r3") = regs->
uregs[rn];
368 register unsigned long rmv
asm(
"r1") = regs->
uregs[rm];
369 unsigned long cpsr = regs->ARM_cpsr;
372 "msr cpsr_fs, %[cpsr] \n\t"
374 "mrs %[cpsr], cpsr \n\t"
375 :
"=r" (rdlov),
"=r" (rdhiv), [cpsr]
"=r" (cpsr)
376 :
"0" (rdlov),
"1" (rdhiv),
"r" (rnv),
"r" (rmv),
377 "2" (cpsr), [
fn]
"r" (p->
ainsn.insn_fn)
378 :
"lr",
"memory",
"cc"
381 regs->
uregs[rdlo] = rdlov;
382 regs->
uregs[rdhi] = rdhiv;
396 static const union decode_item arm_1111_table[] = {
432 static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = {
437 REGS(0, NOPC, 0, 0, 0)),
444 REGS(0, 0, 0, 0, NOPC)),
448 REGS(0, NOPC, 0, 0, NOPC)),
454 DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc,
455 REGS(NOPC, NOPC, 0, 0, NOPC)),
466 static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = {
470 DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
471 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
476 DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc,
477 REGS(NOPC, 0, NOPC, 0, NOPC)),
482 DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc,
483 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
488 static const union decode_item arm_cccc_0000_____1001_table[] = {
493 DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc,
494 REGS(NOPC, 0, NOPC, 0, NOPC)),
500 DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc,
501 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
513 DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
514 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
519 static const union decode_item arm_cccc_0001_____1001_table[] = {
522 #if __LINUX_ARM_ARCH__ < 6
525 DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
526 REGS(NOPC, NOPC, 0, 0, NOPC)),
533 static const union decode_item arm_cccc_000x_____1xx1_table[] = {
549 REGS(NOPCWB, NOPCX, 0, 0, NOPC)),
554 REGS(NOPCWB, NOPCX, 0, 0, 0)),
558 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
564 REGS(NOPCWB, NOPC, 0, 0, NOPC)),
568 REGS(NOPCWB, NOPC, 0, 0, 0)),
574 REGS(NOPCWB, NOPC, 0, 0, 0)),
579 static const union decode_item arm_cccc_000x_table[] = {
592 DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags,
597 DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags,
610 DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags,
617 DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags,
622 DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags,
635 DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
641 static const union decode_item arm_cccc_001x_table[] = {
647 REGS(0, NOPC, 0, 0, 0)),
669 DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags,
674 DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags,
687 DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags,
693 static const union decode_item arm_cccc_0110_____xxx1_table[] = {
697 DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc,
698 REGS(NOPC, NOPC, 0, 0, NOPC)),
705 DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc,
706 REGS(0, NOPC, 0, 0, NOPC)),
713 REGS(0, NOPC, 0, 0, NOPC)),
757 DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc,
758 REGS(NOPC, NOPC, 0, 0, NOPC)),
762 DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc,
763 REGS(NOPC, NOPC, 0, 0, NOPC)),
776 REGS(0, NOPC, 0, 0, NOPC)),
784 DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc,
785 REGS(NOPCX, NOPC, 0, 0, NOPC)),
790 static const union decode_item arm_cccc_0111_____xxx1_table[] = {
798 DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc,
799 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
807 DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc,
808 REGS(NOPC, 0, NOPC, 0, NOPC)),
816 DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc,
817 REGS(NOPC, NOPCX, NOPC, 0, NOPC)),
820 DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc,
821 REGS(NOPC, NOPC, NOPC, 0, NOPC)),
826 REGS(0, NOPC, 0, 0, NOPC)),
830 REGS(0, NOPC, 0, 0, 0)),
834 REGS(0, NOPC, 0, 0, NOPCX)),
839 static const union decode_item arm_cccc_01xx_table[] = {
864 REGS(NOPCWB,
ANY, 0, 0, NOPC)),
869 REGS(NOPCWB,
ANY, 0, 0, NOPC)),
874 static const union decode_item arm_cccc_100x_table[] = {
898 DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table),
904 DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table),
910 DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table),
916 DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table),
922 DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table),
930 DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table),
936 DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table),
942 DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table),
943 DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table),
949 DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table),
955 DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table),
977 #ifdef CONFIG_ARM_KPROBES_TEST_MODULE
984 p->
ainsn.insn_handler(p, regs);