All of lore.kernel.org
 help / color / mirror / Atom feed
* ARM: kprobes: Add support for Thumb-2
@ 2011-07-09 10:56 Tixy
  2011-07-09 10:56 ` [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly Tixy
                   ` (51 more replies)
  0 siblings, 52 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel


On ARM, kprobes uses an undefined instruction as a breakpoint. When this
causes an exception, kprobe_handler() is invoked which calls the
pre_handler function as specified by the user. The original CPU
instruction which the breakpoint replaced then needs singlestepping.
As ARM CPUs don't have any hardware support for this it has to be done
by simulating or emulating the instruction.

'Simulation' is where the instruction's behaviour is duplicated in
C code. 'Emulation' is where the original instruction is rewritten
and executed, often by altering its registers.

This patch series adds support for kprobes on Thumb-2 kernels.
This requires making the framework handle Thumb breakpoints and adding
simulation and emulation routines for the Thumb instruction set.

Note, this series also modifies the existing behaviour in the case when
probes are placed on conditionally executed instructions (see patch 15).


Table of Contents:

Make undefined instruction handlers work for Thumb-2
----------------------------------------------------
  01  Thumb-2: Fix exception return sequence to restore stack correctly
  02  Thumb-2: Support Thumb-2 in undefined instruction handler

Source code reorg
-----------------
  03  kprobes: Rename kprobes-decode.c to kprobes-arm.c
  04  kprobes: Split out internal parts of kprobes.h
  05  kprobes: Add kprobes-common.c
  06  kprobes: Move is_writeback define to header file.
  07  kprobes: Move find_str_pc_offset into kprobes-common.c

Get kprobes infrastructure to support Thumb-2
---------------------------------------------
  08  kprobes: Make str_pc_offset a constant on ARMv7
  09  kprobes: Make kprobes framework work on Thumb-2 kernels
  10  kprobes: Add Thumb instruction decoding stubs
  11  Kconfig: Allow kprobes on Thumb-2 kernels
  12  kprobes: Add Thumb breakpoint support
  13  kprobes: Add condition code checking to Thumb emulation
  14  kprobes: Add it_advance()
  15  kprobes: Don't trigger probes on conditional instructions when condition is false
  16  kprobes: Use conditional breakpoints for ARM probes
  17  kprobes: Add hooks to override singlestep()
  18  kprobes: Extend arch_specific_insn to add pointer to emulated instruction
  19  kprobes: Infrastructure for table driven decoding of CPU instructions

16-bit Thumb instruction decoding and emulation/simulation
----------------------------------------------------------
  20  kprobes: Decode 16-bit Thumb hint instructions
  21  ptrace: Add APSR_MASK definition to ptrace.h
  22  kprobes: Decode 16-bit Thumb data-processing instructions
  23  kprobes: Add bx_write_pc()
  24  kprobes: Decode 16-bit Thumb BX and BLX instructions
  25  kprobes: Decode 16-bit Thumb special data instructions
  26  kprobes: Decode 16-bit Thumb load and store instructions
  27  kprobes: Decode 16-bit Thumb PC- and SP-relative address instructions
  28  kprobes: Decode 16-bit Thumb CBZ and bit manipulation instructions
  29  kprobes: Decode 16-bit Thumb PUSH and POP instructions
  30  kprobes: Decode 16-bit Thumb IT instruction
  31  kprobes: Reject 16-bit Thumb SVC and UNDEFINED instructions
  32  kprobes: Decode 16-bit Thumb branch instructions
  33  kprobes: Reject 16-bit Thumb SETEND, CPS and BKPT instructions

32-bit Thumb instruction decoding and emulation/simulation
----------------------------------------------------------
  34  kprobes: Decode 32-bit Thumb hint instructions
  35  kprobes: Add load_write_pc()
  36  kprobes: Add common decoding function for LDM and STM
  37  kprobes: Optimise emulation of LDM and STM
  38  kprobes: Decode 32-bit Thumb load/store multiple instructions
  39  kprobes: Decode 32-bit Thumb load/store dual and load/store exclusive instructions
  40  kprobes: Decode 32-bit Thumb table branch instructions
  41  kprobes: Decode 32-bit Thumb data-processing (shifted register) instructions
  42  kprobes: Decode 32-bit Thumb data-processing (modified immediate) instructions
  43  kprobes: Decode 32-bit Thumb data-processing (plain binary immediate) instructions
  44  kprobes: Decode 32-bit miscellaneous control instructions
  45  kprobes: Decode 32-bit Thumb branch instructions
  46  kprobes: Reject 32-bit Thumb coprocessor and SIMD instructions
  47  kprobes: Decode 32-bit Thumb memory hint instructions
  48  kprobes: Decode 32-bit Thumb load/store single data item instructions
  49  kprobes: Decode 32-bit Thumb data-processing (register) instructions
  50  kprobes: Decode 32-bit Thumb long multiply and divide instructions
  51  kprobes: Decode 32-bit Thumb multiply and absolute difference instructions


Overall diff stat:

 arch/arm/Kconfig                                   |    2 +-
 arch/arm/include/asm/kprobes.h                     |   28 +-
 arch/arm/include/asm/ptrace.h                      |   11 +-
 arch/arm/kernel/Makefile                           |    7 +-
 arch/arm/kernel/entry-header.S                     |   12 +-
 .../arm/kernel/{kprobes-decode.c => kprobes-arm.c} |  187 +---
 arch/arm/kernel/kprobes-common.c                   |  562 ++++++++
 arch/arm/kernel/kprobes-thumb.c                    | 1462 ++++++++++++++++++++
 arch/arm/kernel/kprobes.c                          |  222 +++-
 arch/arm/kernel/kprobes.h                          |  392 ++++++
 arch/arm/kernel/ptrace.c                           |   28 +-
 arch/arm/kernel/traps.c                            |   17 +-
 12 files changed, 2679 insertions(+), 251 deletions(-)

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-11 18:07   ` Nicolas Pitre
  2011-07-09 10:56 ` [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler Tixy
                   ` (50 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The implementation of svc_exit didn't take into account any stack hole
created by svc_entry; as happens with the undef handler when kprobes are
configured. The fix is to read the saved value of SP rather than trying
to calculate it.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/entry-header.S |   12 +++++-------
 1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 051166c..83e29ad 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -121,15 +121,13 @@
 	.endm
 #else	/* CONFIG_THUMB2_KERNEL */
 	.macro	svc_exit, rpsr
+	ldr	lr, [sp, #S_SP]			@ top of the stack
+	ldrd	r0, r1, [sp, #S_LR]		@ calling lr and pc
 	clrex					@ clear the exclusive monitor
-	ldr	r0, [sp, #S_SP]			@ top of the stack
-	ldr	r1, [sp, #S_PC]			@ return address
-	tst	r0, #4				@ orig stack 8-byte aligned?
-	stmdb	r0, {r1, \rpsr}			@ rfe context
+	stmdb	lr!, {r0, r1, \rpsr}		@ calling lr and rfe context
 	ldmia	sp, {r0 - r12}
-	ldr	lr, [sp, #S_LR]
-	addeq	sp, sp, #S_FRAME_SIZE - 8	@ aligned
-	addne	sp, sp, #S_FRAME_SIZE - 4	@ not aligned
+	mov	sp, lr
+	ldr	lr, [sp], #4
 	rfeia	sp!
 	.endm
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
  2011-07-09 10:56 ` [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-11 18:14   ` Nicolas Pitre
  2011-07-09 10:56 ` [PATCH 03/51] ARM: kprobes: Rename kprobes-decode.c to kprobes-arm.c Tixy
                   ` (49 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This patch allows undef_hook's to be specified for 32-bit Thumb
instructions and also to be used for thumb kernel-side code.

32-bit Thumb instructions are specified in the form:
	((first_half << 16 ) | second_half)
which matches the layout used by the ARM ARM.

ptrace was handling 32-bit Thumb instructions by hooking the first
halfword and manually checking the second half. This method would be
broken by this patch so it is migrated to make use of the new Thumb-2
support.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/include/asm/ptrace.h |    8 ++++++++
 arch/arm/kernel/ptrace.c      |   28 +++-------------------------
 arch/arm/kernel/traps.c       |   17 ++++++++++++++++-
 3 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 312d108..d484871 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -200,6 +200,14 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PREDICATE_ALWAYS	0xe0000000
 
 /*
+ * True if instr is a 32-bit thumb instruction. This works if instr
+ * is the first or only half-word of a thumb instruction. It also works
+ * when instr holds all 32-bits of a wide thumb instruction if stored
+ * in the form (first_half<<16)|(second_half)
+ */
+#define is_wide_instruction(instr)	((unsigned)(instr) >= 0xe800)
+
+/*
  * kprobe-based event tracer support
  */
 #include <linux/stddef.h>
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9726006..897ade0 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -228,34 +228,12 @@ static struct undef_hook thumb_break_hook = {
 	.fn		= break_trap,
 };
 
-static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
-{
-	unsigned int instr2;
-	void __user *pc;
-
-	/* Check the second half of the instruction.  */
-	pc = (void __user *)(instruction_pointer(regs) + 2);
-
-	if (processor_mode(regs) == SVC_MODE) {
-		instr2 = *(u16 *) pc;
-	} else {
-		get_user(instr2, (u16 __user *)pc);
-	}
-
-	if (instr2 == 0xa000) {
-		ptrace_break(current, regs);
-		return 0;
-	} else {
-		return 1;
-	}
-}
-
 static struct undef_hook thumb2_break_hook = {
-	.instr_mask	= 0xffff,
-	.instr_val	= 0xf7f0,
+	.instr_mask	= 0xffffffff,
+	.instr_val	= 0xf7f0a000,
 	.cpsr_mask	= PSR_T_BIT,
 	.cpsr_val	= PSR_T_BIT,
-	.fn		= thumb2_break_trap,
+	.fn		= break_trap,
 };
 
 static int __init ptrace_break_init(void)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 6807cb1..2d3436e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	pc = (void __user *)instruction_pointer(regs);
 
 	if (processor_mode(regs) == SVC_MODE) {
-		instr = *(u32 *) pc;
+#ifdef CONFIG_THUMB2_KERNEL
+		if (thumb_mode(regs)) {
+			instr = ((u16 *)pc)[0];
+			if (is_wide_instruction(instr)) {
+				instr <<= 16;
+				instr |= ((u16 *)pc)[1];
+			}
+		} else
+#endif
+			instr = *(u32 *) pc;
 	} else if (thumb_mode(regs)) {
 		get_user(instr, (u16 __user *)pc);
+		if (is_wide_instruction(instr)) {
+			unsigned int instr2;
+			get_user(instr2, (u16 __user *)pc+1);
+			instr <<= 16;
+			instr |= instr2;
+		}
 	} else {
 		get_user(instr, (u32 __user *)pc);
 	}
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 03/51] ARM: kprobes: Rename kprobes-decode.c to kprobes-arm.c
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
  2011-07-09 10:56 ` [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly Tixy
  2011-07-09 10:56 ` [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 04/51] ARM: kprobes: Split out internal parts of kprobes.h Tixy
                   ` (48 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This file contains decoding and emulation functions for the ARM
instruction set. As we will later be adding a file for Thumb and a
file with common decoding functions, this renaming makes things clearer.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/Makefile                           |    3 ++-
 .../arm/kernel/{kprobes-decode.c => kprobes-arm.c} |    0
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a5b31af..914c7a6 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -37,7 +37,8 @@ obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
+obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-arm.c
similarity index 100%
rename from arch/arm/kernel/kprobes-decode.c
rename to arch/arm/kernel/kprobes-arm.c
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 04/51] ARM: kprobes: Split out internal parts of kprobes.h
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (2 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 03/51] ARM: kprobes: Rename kprobes-decode.c to kprobes-arm.c Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 05/51] ARM: kprobes: Add kprobes-common.c Tixy
                   ` (47 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Later, we will be adding a considerable amount of internal
implementation definitions to kprobe header files and it would be good
to have these in local header file along side the source code, rather
than pollute the existing header which is include by all users of
kprobes.

To this end, we add arch/arm/kernel/kprobes.h and move into this the
existing internal defintions from arch/arm/include/asm/kprobes.h

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/include/asm/kprobes.h |   17 -----------------
 arch/arm/kernel/kprobes.h      |   37 +++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/kprobes-arm.c  |    2 ++
 arch/arm/kernel/kprobes.c      |    2 ++
 4 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index e46bdd0..57d37d5 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -24,12 +24,6 @@
 #define MAX_INSN_SIZE			2
 #define MAX_STACK_SIZE			64	/* 32 would probably be OK */
 
-/*
- * This undefined instruction must be unique and
- * reserved solely for kprobes' use.
- */
-#define KPROBE_BREAKPOINT_INSTRUCTION	0xe7f001f8
-
 #define regs_return_value(regs)		((regs)->ARM_r0)
 #define flush_insn_slot(p)		do { } while (0)
 #define kretprobe_blacklist_size	0
@@ -62,20 +56,9 @@ struct kprobe_ctlblk {
 };
 
 void arch_remove_kprobe(struct kprobe *);
-void kretprobe_trampoline(void);
-
 int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
 int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
-enum kprobe_insn {
-	INSN_REJECTED,
-	INSN_GOOD,
-	INSN_GOOD_NO_SLOT
-};
-
-enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
-					struct arch_specific_insn *);
-void __init arm_kprobe_decode_init(void);
 
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
new file mode 100644
index 0000000..87a5241
--- /dev/null
+++ b/arch/arm/kernel/kprobes.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/kernel/kprobes.h
+ *
+ * Contents moved from arch/arm/include/asm/kprobes.h which is
+ * Copyright (C) 2006, 2007 Motorola Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _ARM_KERNEL_KPROBES_H
+#define _ARM_KERNEL_KPROBES_H
+
+/*
+ * This undefined instruction must be unique and
+ * reserved solely for kprobes' use.
+ */
+#define KPROBE_BREAKPOINT_INSTRUCTION	0xe7f001f8
+
+enum kprobe_insn {
+	INSN_REJECTED,
+	INSN_GOOD,
+	INSN_GOOD_NO_SLOT
+};
+
+enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
+					struct arch_specific_insn *);
+
+void __init arm_kprobe_decode_init(void);
+
+#endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 15eeff6..976ce14 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -61,6 +61,8 @@
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
 
+#include "kprobes.h"
+
 #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
 
 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 1656c87..3ba5f8d 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -28,6 +28,8 @@
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
 
+#include "kprobes.h"
+
 #define MIN_STACK_SIZE(addr) 				\
 	min((unsigned long)MAX_STACK_SIZE,		\
 	    (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 05/51] ARM: kprobes: Add kprobes-common.c
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (3 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 04/51] ARM: kprobes: Split out internal parts of kprobes.h Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 06/51] ARM: kprobes: Move is_writeback define to header file Tixy
                   ` (46 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This file will contain the instruction decoding and emulation code
which is common to both ARM and Thumb instruction sets.

For now, we will just move over condition_checks from kprobes-arm.c
This table is also renamed to kprobe_condition_checks to avoid polluting
the public namespace with a too generic name.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/Makefile         |    2 +-
 arch/arm/kernel/kprobes.h        |    2 +
 arch/arm/kernel/kprobes-arm.c    |   92 +---------------------------------
 arch/arm/kernel/kprobes-common.c |  105 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 109 insertions(+), 92 deletions(-)

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 914c7a6..a22b8f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -37,7 +37,7 @@ obj-$(CONFIG_HAVE_ARM_TWD)	+= smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES)		+= kprobes.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-common.o
 obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 87a5241..792f231 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -34,4 +34,6 @@ enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
 
 void __init arm_kprobe_decode_init(void);
 
+extern kprobe_check_cc * const kprobe_condition_checks[16];
+
 #endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 976ce14..8d4464f 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -1523,96 +1523,6 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 	return INSN_REJECTED;
 }
 
-static unsigned long __kprobes __check_eq(unsigned long cpsr)
-{
-	return cpsr & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_ne(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_Z_BIT;
-}
-
-static unsigned long __kprobes __check_cs(unsigned long cpsr)
-{
-	return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_cc(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_mi(unsigned long cpsr)
-{
-	return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_pl(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_vs(unsigned long cpsr)
-{
-	return cpsr & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_vc(unsigned long cpsr)
-{
-	return (~cpsr) & PSR_V_BIT;
-}
-
-static unsigned long __kprobes __check_hi(unsigned long cpsr)
-{
-	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
-	return cpsr & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ls(unsigned long cpsr)
-{
-	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
-	return (~cpsr) & PSR_C_BIT;
-}
-
-static unsigned long __kprobes __check_ge(unsigned long cpsr)
-{
-	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	return (~cpsr) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_lt(unsigned long cpsr)
-{
-	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	return cpsr & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_gt(unsigned long cpsr)
-{
-	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
-	return (~temp) & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_le(unsigned long cpsr)
-{
-	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
-	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
-	return temp & PSR_N_BIT;
-}
-
-static unsigned long __kprobes __check_al(unsigned long cpsr)
-{
-	return true;
-}
-
-static kprobe_check_cc * const condition_checks[16] = {
-	&__check_eq, &__check_ne, &__check_cs, &__check_cc,
-	&__check_mi, &__check_pl, &__check_vs, &__check_vc,
-	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
-	&__check_gt, &__check_le, &__check_al, &__check_al
-};
-
 /* Return:
  *   INSN_REJECTED     If instruction is one not allowed to kprobe,
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
@@ -1628,7 +1538,7 @@ static kprobe_check_cc * const condition_checks[16] = {
 enum kprobe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-	asi->insn_check_cc = condition_checks[insn>>28];
+	asi->insn_check_cc = kprobe_condition_checks[insn>>28];
 	asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
 
 	if ((insn & 0xf0000000) == 0xf0000000)
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
new file mode 100644
index 0000000..794827e
--- /dev/null
+++ b/arch/arm/kernel/kprobes-common.c
@@ -0,0 +1,105 @@
+/*
+ * arch/arm/kernel/kprobes-common.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
+{
+	return cpsr & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_Z_BIT;
+}
+
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+	return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+	return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+	return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+	return true;
+}
+
+kprobe_check_cc * const kprobe_condition_checks[16] = {
+	&__check_eq, &__check_ne, &__check_cs, &__check_cc,
+	&__check_mi, &__check_pl, &__check_vs, &__check_vc,
+	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
+	&__check_gt, &__check_le, &__check_al, &__check_al
+};
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 06/51] ARM: kprobes: Move is_writeback define to header file.
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (4 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 05/51] ARM: kprobes: Add kprobes-common.c Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 07/51] ARM: kprobes: Move find_str_pc_offset into kprobes-common.c Tixy
                   ` (45 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This will be used later in other files.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h     |    6 ++++++
 arch/arm/kernel/kprobes-arm.c |    6 ------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 792f231..4de2f37 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -36,4 +36,10 @@ void __init arm_kprobe_decode_init(void);
 
 extern kprobe_check_cc * const kprobe_condition_checks[16];
 
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
 #endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 8d4464f..3c4678e 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -69,12 +69,6 @@
 
 #define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
 
-/*
- * Test if load/store instructions writeback the address register.
- * if P (bit 24) == 0 or W (bit 21) == 1
- */
-#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
-
 #define PSR_fs	(PSR_f|PSR_s)
 
 #define KPROBE_RETURN_INSTRUCTION	0xe1a0f00e	/* mov pc, lr */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 07/51] ARM: kprobes: Move find_str_pc_offset into kprobes-common.c
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (5 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 06/51] ARM: kprobes: Move is_writeback define to header file Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 08/51] ARM: kprobes: Make str_pc_offset a constant on ARMv7 Tixy
                   ` (44 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Move str_pc_offset into kprobes-common.c as it will be needed by common
code later.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |    2 ++
 arch/arm/kernel/kprobes-arm.c    |   28 ----------------------------
 arch/arm/kernel/kprobes-common.c |   33 +++++++++++++++++++++++++++++++++
 3 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 4de2f37..43f630d 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -36,6 +36,8 @@ void __init arm_kprobe_decode_init(void);
 
 extern kprobe_check_cc * const kprobe_condition_checks[16];
 
+extern int str_pc_offset;
+
 /*
  * Test if load/store instructions writeback the address register.
  * if P (bit 24) == 0 or W (bit 21) == 1
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 3c4678e..0262b29 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -92,29 +92,6 @@ union reg_pair {
 };
 
 /*
- * For STR and STM instructions, an ARM core may choose to use either
- * a +8 or a +12 displacement from the current instruction's address.
- * Whichever value is chosen for a given core, it must be the same for
- * both instructions and may not change.  This function measures it.
- */
-
-static int str_pc_offset;
-
-static void __init find_str_pc_offset(void)
-{
-	int addr, scratch, ret;
-
-	__asm__ (
-		"sub	%[ret], pc, #4		\n\t"
-		"str	pc, %[addr]		\n\t"
-		"ldr	%[scr], %[addr]		\n\t"
-		"sub	%[ret], %[scr], %[ret]	\n\t"
-		: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
-
-	str_pc_offset = ret;
-}
-
-/*
  * The insnslot_?arg_r[w]flags() functions below are to keep the
  * msr -> *fn -> mrs instruction sequences indivisible so that
  * the state of the CPSR flags aren't inadvertently modified
@@ -1569,8 +1546,3 @@ arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
 	return space_cccc_11xx(insn, asi);
 }
-
-void __init arm_kprobe_decode_init(void)
-{
-	find_str_pc_offset();
-}
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 794827e..e18576c 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -3,6 +3,9 @@
  *
  * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
  *
+ * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is
+ * Copyright (C) 2006, 2007 Motorola Inc.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -14,6 +17,36 @@
 #include "kprobes.h"
 
 
+/*
+ * For STR and STM instructions, an ARM core may choose to use either
+ * a +8 or a +12 displacement from the current instruction's address.
+ * Whichever value is chosen for a given core, it must be the same for
+ * both instructions and may not change.  This function measures it.
+ */
+
+int str_pc_offset;
+
+void __init find_str_pc_offset(void)
+{
+	int addr, scratch, ret;
+
+	__asm__ (
+		"sub	%[ret], pc, #4		\n\t"
+		"str	pc, %[addr]		\n\t"
+		"ldr	%[scr], %[addr]		\n\t"
+		"sub	%[ret], %[scr], %[ret]	\n\t"
+		: [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr));
+
+	str_pc_offset = ret;
+}
+
+
+void __init arm_kprobe_decode_init(void)
+{
+	find_str_pc_offset();
+}
+
+
 static unsigned long __kprobes __check_eq(unsigned long cpsr)
 {
 	return cpsr & PSR_Z_BIT;
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 08/51] ARM: kprobes: Make str_pc_offset a constant on ARMv7
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (6 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 07/51] ARM: kprobes: Move find_str_pc_offset into kprobes-common.c Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 09/51] ARM: kprobes: Make kprobes framework work on Thumb-2 kernels Tixy
                   ` (43 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The str_pc_offset value is architecturally defined on ARMv7 onwards so
we can make it a compile time constant. This means on Thumb kernels the
runtime checking code isn't needed, which saves us from having to fix it
to work for Thumb.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |   14 ++++++++++++++
 arch/arm/kernel/kprobes-common.c |    4 ++++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 43f630d..406bb2d 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -36,7 +36,21 @@ void __init arm_kprobe_decode_init(void);
 
 extern kprobe_check_cc * const kprobe_condition_checks[16];
 
+
+#if __LINUX_ARM_ARCH__ >= 7
+
+/* str_pc_offset is architecturally defined from ARMv7 onwards */
+#define str_pc_offset 8
+#define find_str_pc_offset()
+
+#else /* __LINUX_ARM_ARCH__ < 7 */
+
+/* We need a run-time check to determine str_pc_offset */
 extern int str_pc_offset;
+void __init find_str_pc_offset(void);
+
+#endif
+
 
 /*
  * Test if load/store instructions writeback the address register.
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index e18576c..87e91ce 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -17,6 +17,8 @@
 #include "kprobes.h"
 
 
+#ifndef find_str_pc_offset
+
 /*
  * For STR and STM instructions, an ARM core may choose to use either
  * a +8 or a +12 displacement from the current instruction's address.
@@ -40,6 +42,8 @@ void __init find_str_pc_offset(void)
 	str_pc_offset = ret;
 }
 
+#endif /* !find_str_pc_offset */
+
 
 void __init arm_kprobe_decode_init(void)
 {
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 09/51] ARM: kprobes: Make kprobes framework work on Thumb-2 kernels
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (7 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 08/51] ARM: kprobes: Make str_pc_offset a constant on ARMv7 Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 10/51] ARM: kprobes: Add Thumb instruction decoding stubs Tixy
                   ` (42 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Fix up kprobes framework so that it builds and correctly interworks on
Thumb-2 kernels.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.c |   37 +++++++++++++++++++++++++++++++++++--
 1 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 3ba5f8d..0e47d3d 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -302,7 +302,11 @@ void __naked __kprobes kretprobe_trampoline(void)
 		"bl	trampoline_handler	\n\t"
 		"mov	lr, r0			\n\t"
 		"ldmia	sp!, {r0 - r11}		\n\t"
+#ifdef CONFIG_THUMB2_KERNEL
+		"bx	lr			\n\t"
+#else
 		"mov	pc, lr			\n\t"
+#endif
 		: : : "memory");
 }
 
@@ -380,11 +384,22 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 	struct jprobe *jp = container_of(p, struct jprobe, kp);
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	long sp_addr = regs->ARM_sp;
+	long cpsr;
 
 	kcb->jprobe_saved_regs = *regs;
 	memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
 	regs->ARM_pc = (long)jp->entry;
-	regs->ARM_cpsr |= PSR_I_BIT;
+
+	cpsr = regs->ARM_cpsr | PSR_I_BIT;
+#ifdef CONFIG_THUMB2_KERNEL
+	/* Set correct Thumb state in cpsr */
+	if (regs->ARM_pc & 1)
+		cpsr |= PSR_T_BIT;
+	else
+		cpsr &= ~PSR_T_BIT;
+#endif
+	regs->ARM_cpsr = cpsr;
+
 	preempt_disable();
 	return 1;
 }
@@ -406,7 +421,12 @@ void __kprobes jprobe_return(void)
 		 * This is to prevent any simulated instruction from writing
 		 * over the regs when they are accessing the stack.
 		 */
+#ifdef CONFIG_THUMB2_KERNEL
+		"sub    r0, %0, %1		\n\t"
+		"mov    sp, r0			\n\t"
+#else
 		"sub    sp, %0, %1		\n\t"
+#endif
 		"ldr    r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
 		"str    %0, [sp, %2]		\n\t"
 		"str    r0, [sp, %3]		\n\t"
@@ -417,15 +437,28 @@ void __kprobes jprobe_return(void)
 		 * Return to the context saved by setjmp_pre_handler
 		 * and restored by longjmp_break_handler.
 		 */
+#ifdef CONFIG_THUMB2_KERNEL
+		"ldr	lr, [sp, %2]		\n\t" /* lr = saved sp */
+		"ldrd	r0, r1, [sp, %5]	\n\t" /* r0,r1 = saved lr,pc */
+		"ldr	r2, [sp, %4]		\n\t" /* r2 = saved psr */
+		"stmdb	lr!, {r0, r1, r2}	\n\t" /* push saved lr and */
+						      /* rfe context */
+		"ldmia	sp, {r0 - r12}		\n\t"
+		"mov	sp, lr			\n\t"
+		"ldr	lr, [sp], #4		\n\t"
+		"rfeia	sp!			\n\t"
+#else
 		"ldr	r0, [sp, %4]		\n\t"
 		"msr	cpsr_cxsf, r0		\n\t"
 		"ldmia	sp, {r0 - pc}		\n\t"
+#endif
 		:
 		: "r" (kcb->jprobe_saved_regs.ARM_sp),
 		  "I" (sizeof(struct pt_regs) * 2),
 		  "J" (offsetof(struct pt_regs, ARM_sp)),
 		  "J" (offsetof(struct pt_regs, ARM_pc)),
-		  "J" (offsetof(struct pt_regs, ARM_cpsr))
+		  "J" (offsetof(struct pt_regs, ARM_cpsr)),
+		  "J" (offsetof(struct pt_regs, ARM_lr))
 		: "memory", "cc");
 }
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 10/51] ARM: kprobes: Add Thumb instruction decoding stubs
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (8 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 09/51] ARM: kprobes: Make kprobes framework work on Thumb-2 kernels Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:56 ` [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels Tixy
                   ` (41 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Extend arch_prepare_kprobe to support probing of Thumb code. For
the actual decoding of Thumb instructions, stub functions are
added which currently just reject the probe.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/Makefile        |    4 ++++
 arch/arm/kernel/kprobes.h       |   13 +++++++++++++
 arch/arm/kernel/kprobes-thumb.c |   26 ++++++++++++++++++++++++++
 arch/arm/kernel/kprobes.c       |   20 ++++++++++++++++++--
 4 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a22b8f1..f7887dc 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -38,7 +38,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-common.o
+ifdef CONFIG_THUMB2_KERNEL
+obj-$(CONFIG_KPROBES)		+= kprobes-thumb.o
+else
 obj-$(CONFIG_KPROBES)		+= kprobes-arm.o
+endif
 obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 406bb2d..86abfab 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -29,8 +29,21 @@ enum kprobe_insn {
 	INSN_GOOD_NO_SLOT
 };
 
+typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t,
+						struct arch_specific_insn *);
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t,
+						struct arch_specific_insn *);
+enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t,
+						struct arch_specific_insn *);
+
+#else /* !CONFIG_THUMB2_KERNEL */
+
 enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t,
 					struct arch_specific_insn *);
+#endif
 
 void __init arm_kprobe_decode_init(void);
 
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
new file mode 100644
index 0000000..ac6b2d1
--- /dev/null
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/kernel/kprobes-thumb.c
+ *
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+
+#include "kprobes.h"
+
+enum kprobe_insn __kprobes
+thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	return INSN_REJECTED;
+}
+
+enum kprobe_insn __kprobes
+thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	return INSN_REJECTED;
+}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 0e47d3d..0df2d6d 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -51,16 +51,32 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	kprobe_opcode_t insn;
 	kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
 	unsigned long addr = (unsigned long)p->addr;
+	kprobe_decode_insn_t *decode_insn;
 	int is;
 
-	if (addr & 0x3 || in_exception_text(addr))
+	if (in_exception_text(addr))
 		return -EINVAL;
 
+#ifdef CONFIG_THUMB2_KERNEL
+	addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
+	insn = ((u16 *)addr)[0];
+	if (is_wide_instruction(insn)) {
+		insn <<= 16;
+		insn |= ((u16 *)addr)[1];
+		decode_insn = thumb32_kprobe_decode_insn;
+	} else
+		decode_insn = thumb16_kprobe_decode_insn;
+#else /* !CONFIG_THUMB2_KERNEL */
+	if (addr & 0x3)
+		return -EINVAL;
 	insn = *p->addr;
+	decode_insn = arm_kprobe_decode_insn;
+#endif
+
 	p->opcode = insn;
 	p->ainsn.insn = tmp_insn;
 
-	switch (arm_kprobe_decode_insn(insn, &p->ainsn)) {
+	switch ((*decode_insn)(insn, &p->ainsn)) {
 	case INSN_REJECTED:	/* not supported */
 		return -EINVAL;
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (9 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 10/51] ARM: kprobes: Add Thumb instruction decoding stubs Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-11 11:01   ` Sergei Shtylyov
  2011-07-09 10:56 ` [PATCH 12/51] ARM: kprobes: Add Thumb breakpoint support Tixy
                   ` (40 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/Kconfig |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9adc278..b4177c5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,7 +10,7 @@ config ARM
 	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_ARCH_KGDB
-	select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
+	select HAVE_KPROBES if (!XIP_KERNEL)
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 12/51] ARM: kprobes: Add Thumb breakpoint support
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (10 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels Tixy
@ 2011-07-09 10:56 ` Tixy
  2011-07-09 10:57 ` [PATCH 13/51] ARM: kprobes: Add condition code checking to Thumb emulation Tixy
                   ` (39 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Extend the breakpoint insertion and catching functions to support Thumb
code.

As breakpoints are no longer of a fixed size, the flush_insns macro
is modified to take a size argument instead of an instruction count.

Note, we need both 16- and 32-bit Thumb breakpoints, because if we
were to use a 16-bit breakpoint to replace a 32-bit instruction which
was in an IT block, and the condition check failed, then the breakpoint
may not fire (it's unpredictable behaviour) and the CPU could then try
and execute the second half of the 32-bit Thumb instruction.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h |    7 ++-
 arch/arm/kernel/kprobes.c |  122 ++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 115 insertions(+), 14 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 86abfab..a84b14d 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -18,10 +18,13 @@
 #define _ARM_KERNEL_KPROBES_H
 
 /*
- * This undefined instruction must be unique and
+ * These undefined instructions must be unique and
  * reserved solely for kprobes' use.
  */
-#define KPROBE_BREAKPOINT_INSTRUCTION	0xe7f001f8
+#define KPROBE_ARM_BREAKPOINT_INSTRUCTION	0xe7f001f8
+#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION	0xde18
+#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION	0xf7f0a018
+
 
 enum kprobe_insn {
 	INSN_REJECTED,
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 0df2d6d..b8f5b3b 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -34,10 +34,10 @@
 	min((unsigned long)MAX_STACK_SIZE,		\
 	    (unsigned long)current_thread_info() + THREAD_START_SP - (addr))
 
-#define flush_insns(addr, cnt) 				\
+#define flush_insns(addr, size)				\
 	flush_icache_range((unsigned long)(addr),	\
 			   (unsigned long)(addr) +	\
-			   sizeof(kprobe_opcode_t) * (cnt))
+			   (size))
 
 /* Used as a marker in ARM_pc to note when we're in a jprobe. */
 #define JPROBE_MAGIC_ADDR		0xffffffff
@@ -86,7 +86,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 			return -ENOMEM;
 		for (is = 0; is < MAX_INSN_SIZE; ++is)
 			p->ainsn.insn[is] = tmp_insn[is];
-		flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
+		flush_insns(p->ainsn.insn,
+				sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
 		break;
 
 	case INSN_GOOD_NO_SLOT:	/* instruction doesn't need insn slot */
@@ -97,24 +98,82 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	return 0;
 }
 
+#ifdef CONFIG_THUMB2_KERNEL
+
+/*
+ * For a 32-bit Thumb breakpoint spanning two memory words we need to take
+ * special precautions to insert the breakpoint atomically, especially on SMP
+ * systems. This is achieved by calling this arming function using stop_machine.
+ */
+int __kprobes set_t32_breakpoint(void *addr)
+{
+	((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
+	((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
+	flush_insns(addr, 2*sizeof(u16));
+	return 0;
+}
+
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	*p->addr = KPROBE_BREAKPOINT_INSTRUCTION;
-	flush_insns(p->addr, 1);
+	uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
+
+	if (!is_wide_instruction(p->opcode)) {
+		*(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
+		flush_insns(addr, sizeof(u16));
+	} else if (addr & 2) {
+		/* A 32-bit instruction spanning two words needs special care */
+		stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+	} else {
+		/* Word aligned 32-bit instruction can be written atomically */
+		u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
+#ifndef __ARMEB__ /* Swap halfwords for little-endian */
+		bkp = (bkp >> 16) | (bkp << 16);
+#endif
+		*(u32 *)addr = bkp;
+		flush_insns(addr, sizeof(u32));
+	}
 }
 
+#else /* !CONFIG_THUMB2_KERNEL */
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
+	flush_insns(p->addr, sizeof(p->addr[0]));
+}
+
+#endif /* !CONFIG_THUMB2_KERNEL */
+
 /*
  * The actual disarming is done here on each CPU and synchronized using
  * stop_machine. This synchronization is necessary on SMP to avoid removing
  * a probe between the moment the 'Undefined Instruction' exception is raised
  * and the moment the exception handler reads the faulting instruction from
- * memory.
+ * memory. It is also needed to atomically set the two half-words of a 32-bit
+ * Thumb breakpoint.
  */
 int __kprobes __arch_disarm_kprobe(void *p)
 {
 	struct kprobe *kp = p;
+#ifdef CONFIG_THUMB2_KERNEL
+	u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
+	kprobe_opcode_t insn = kp->opcode;
+	unsigned int len;
+
+	if (is_wide_instruction(insn)) {
+		((u16 *)addr)[0] = insn>>16;
+		((u16 *)addr)[1] = insn;
+		len = 2*sizeof(u16);
+	} else {
+		((u16 *)addr)[0] = insn;
+		len = sizeof(u16);
+	}
+	flush_insns(addr, len);
+
+#else /* !CONFIG_THUMB2_KERNEL */
 	*kp->addr = kp->opcode;
-	flush_insns(kp->addr, 1);
+	flush_insns(kp->addr, sizeof(kp->addr[0]));
+#endif
 	return 0;
 }
 
@@ -167,11 +226,23 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p, *cur;
 	struct kprobe_ctlblk *kcb;
-	kprobe_opcode_t	*addr = (kprobe_opcode_t *)regs->ARM_pc;
 
 	kcb = get_kprobe_ctlblk();
 	cur = kprobe_running();
-	p = get_kprobe(addr);
+
+#ifdef CONFIG_THUMB2_KERNEL
+	/*
+	 * First look for a probe which was registered using an address with
+	 * bit 0 set, this is the usual situation for pointers to Thumb code.
+	 * If not found, fallback to looking for one with bit 0 clear.
+	 */
+	p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
+	if (!p)
+		p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+
+#else /* ! CONFIG_THUMB2_KERNEL */
+	p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
+#endif
 
 	if (p) {
 		if (cur) {
@@ -511,17 +582,44 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 	return 0;
 }
 
-static struct undef_hook kprobes_break_hook = {
+#ifdef CONFIG_THUMB2_KERNEL
+
+static struct undef_hook kprobes_thumb16_break_hook = {
+	.instr_mask	= 0xffff,
+	.instr_val	= KPROBE_THUMB16_BREAKPOINT_INSTRUCTION,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= kprobe_trap_handler,
+};
+
+static struct undef_hook kprobes_thumb32_break_hook = {
+	.instr_mask	= 0xffffffff,
+	.instr_val	= KPROBE_THUMB32_BREAKPOINT_INSTRUCTION,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= kprobe_trap_handler,
+};
+
+#else  /* !CONFIG_THUMB2_KERNEL */
+
+static struct undef_hook kprobes_arm_break_hook = {
 	.instr_mask	= 0xffffffff,
-	.instr_val	= KPROBE_BREAKPOINT_INSTRUCTION,
+	.instr_val	= KPROBE_ARM_BREAKPOINT_INSTRUCTION,
 	.cpsr_mask	= MODE_MASK,
 	.cpsr_val	= SVC_MODE,
 	.fn		= kprobe_trap_handler,
 };
 
+#endif /* !CONFIG_THUMB2_KERNEL */
+
 int __init arch_init_kprobes()
 {
 	arm_kprobe_decode_init();
-	register_undef_hook(&kprobes_break_hook);
+#ifdef CONFIG_THUMB2_KERNEL
+	register_undef_hook(&kprobes_thumb16_break_hook);
+	register_undef_hook(&kprobes_thumb32_break_hook);
+#else
+	register_undef_hook(&kprobes_arm_break_hook);
+#endif
 	return 0;
 }
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 13/51] ARM: kprobes: Add condition code checking to Thumb emulation
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (11 preceding siblings ...)
  2011-07-09 10:56 ` [PATCH 12/51] ARM: kprobes: Add Thumb breakpoint support Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 14/51] ARM: kprobes: Add it_advance() Tixy
                   ` (38 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index ac6b2d1..24a188b 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -13,14 +13,36 @@
 
 #include "kprobes.h"
 
+
+/*
+ * True if current instruction is in an IT block.
+ */
+#define in_it_block(cpsr)	((cpsr & 0x06000c00) != 0x00000000)
+
+/*
+ * Return the condition code to check for the currently executing instruction.
+ * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if
+ * in_it_block returns true.
+ */
+#define current_cond(cpsr)	((cpsr >> 12) & 0xf)
+
+static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
+{
+	if (unlikely(in_it_block(cpsr)))
+		return kprobe_condition_checks[current_cond(cpsr)](cpsr);
+	return true;
+}
+
 enum kprobe_insn __kprobes
 thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_check_cc = thumb_check_cc;
 	return INSN_REJECTED;
 }
 
 enum kprobe_insn __kprobes
 thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_check_cc = thumb_check_cc;
 	return INSN_REJECTED;
 }
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 14/51] ARM: kprobes: Add it_advance()
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (12 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 13/51] ARM: kprobes: Add condition code checking to Thumb emulation Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false Tixy
                   ` (37 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This advances the ITSTATE bits in CPSR to their values for the next
instruction.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index a84b14d..5e2485c 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -69,6 +69,31 @@ void __init find_str_pc_offset(void);
 
 
 /*
+ * Update ITSTATE after normal execution of an IT block instruction.
+ *
+ * The 8 IT state bits are split into two parts in CPSR:
+ *	ITSTATE<1:0> are in CPSR<26:25>
+ *	ITSTATE<7:2> are in CPSR<15:10>
+ */
+static inline unsigned long it_advance(unsigned long cpsr)
+	{
+	if ((cpsr & 0x06000400) == 0) {
+		/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
+		cpsr &= ~PSR_IT_MASK;
+	} else {
+		/* We need to shift left ITSTATE<4:0> */
+		const unsigned long mask = 0x06001c00;  /* Mask ITSTATE<4:0> */
+		unsigned long it = cpsr & mask;
+		it <<= 1;
+		it |= it >> (27 - 10);  /* Carry ITSTATE<2> to correct place */
+		it &= mask;
+		cpsr &= ~mask;
+		cpsr |= it;
+	}
+	return cpsr;
+}
+
+/*
  * Test if load/store instructions writeback the address register.
  * if P (bit 24) == 0 or W (bit 21) == 1
  */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (13 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 14/51] ARM: kprobes: Add it_advance() Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-11 19:04   ` Nicolas Pitre
  2011-07-09 10:57 ` [PATCH 16/51] ARM: kprobes: Use conditional breakpoints for ARM probes Tixy
                   ` (36 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This patch changes the behavior of kprobes on ARM so that:

    Kprobes on conditional instructions don't trigger when the
    condition is false. For conditional branches, this means that
    they don't trigger in the branch not taken case.

Rationale:

When probes are placed onto conditionally executed instructions in a
Thumb IT block, they may not fire if the condition is not met. This
is because we use invalid instructions for breakpoints and "it is
IMPLEMENTATION DEFINED whether the instruction executes as a NOP or
causes an Undefined Instruction exception". Therefore, for consistency,
we will ignore all probes on any conditional instructions when the
condition is false. Alternative solutions seem to be too complex to
implement or inconsistent.

This issue was discussed on linux.arm.kernel in the thread titled
"[RFC] kprobes with thumb2 conditional code" See
http://comments.gmane.org/gmane.linux.linaro.devel/2985

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.c |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index b8f5b3b..7a9be60 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -207,6 +207,20 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
 	__get_cpu_var(current_kprobe) = p;
 }
 
+static void __kprobes
+singlestep_skip(struct kprobe *p, struct pt_regs *regs)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+	if (is_wide_instruction(p->opcode))
+		regs->ARM_pc += 4;
+	else
+		regs->ARM_pc += 2;
+#else
+	regs->ARM_pc += 4;
+#endif
+}
+
 static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
 				 struct kprobe_ctlblk *kcb)
 {
@@ -262,7 +276,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 				/* impossible cases */
 				BUG();
 			}
-		} else {
+		} else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
+			/* Probe hit and conditional execution check ok. */
 			set_current_kprobe(p);
 			kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
@@ -282,6 +297,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 				}
 				reset_current_kprobe();
 			}
+		} else {
+			/*
+			 * Probe hit but conditional execution check failed,
+			 * so just skip the instruction and continue as if
+			 * nothing had happened.
+			 */
+			singlestep_skip(p, regs);
 		}
 	} else if (cur) {
 		/* We probably hit a jprobe.  Call its break handler. */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 16/51] ARM: kprobes: Use conditional breakpoints for ARM probes
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (14 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 17/51] ARM: kprobes: Add hooks to override singlestep() Tixy
                   ` (35 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Now we no longer trigger probes on conditional instructions when the
condition is false, we can make use of conditional instructions as
breakpoints in ARM code to avoid taking unnecessary exceptions.

Note, we can't rely on not getting an exception when the condition check
fails, as that is Implementation Defined on newer ARM architectures. We
therefore still need to perform manual condition checks as well.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h |    2 +-
 arch/arm/kernel/kprobes.c |   10 ++++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 5e2485c..e3803c6 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -21,7 +21,7 @@
  * These undefined instructions must be unique and
  * reserved solely for kprobes' use.
  */
-#define KPROBE_ARM_BREAKPOINT_INSTRUCTION	0xe7f001f8
+#define KPROBE_ARM_BREAKPOINT_INSTRUCTION	0x07f001f8
 #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION	0xde18
 #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION	0xf7f0a018
 
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 7a9be60..9104b03 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -138,7 +138,13 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	*p->addr = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
+	kprobe_opcode_t insn = p->opcode;
+	kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
+	if (insn >= 0xe0000000)
+		brkp |= 0xe0000000;  /* Unconditional instruction */
+	else
+		brkp |= insn & 0xf0000000;  /* Copy condition from insn */
+	*p->addr = brkp;
 	flush_insns(p->addr, sizeof(p->addr[0]));
 }
 
@@ -625,7 +631,7 @@ static struct undef_hook kprobes_thumb32_break_hook = {
 #else  /* !CONFIG_THUMB2_KERNEL */
 
 static struct undef_hook kprobes_arm_break_hook = {
-	.instr_mask	= 0xffffffff,
+	.instr_mask	= 0x0fffffff,
 	.instr_val	= KPROBE_ARM_BREAKPOINT_INSTRUCTION,
 	.cpsr_mask	= MODE_MASK,
 	.cpsr_val	= SVC_MODE,
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 17/51] ARM: kprobes: Add hooks to override singlestep()
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (15 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 16/51] ARM: kprobes: Use conditional breakpoints for ARM probes Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction Tixy
                   ` (34 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

When a probe fires we must single-step the instruction which was
replaced by a breakpoint. As the steps to do this vary between ARM and
Thumb instructions we need a way to customise single-stepping.

This is done by adding a new hook called insn_singlestep to
arch_specific_insn which is initialised by the instruction decoding
functions.

These single-step hooks must update PC and call the instruction handler.
For Thumb instructions an additional step of updating ITSTATE is needed.
We do this after calling the handler because some handlers will need to
test if they are running in an IT block.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/include/asm/kprobes.h  |    9 +++++----
 arch/arm/kernel/kprobes-arm.c   |    7 +++++++
 arch/arm/kernel/kprobes-thumb.c |   16 ++++++++++++++++
 arch/arm/kernel/kprobes.c       |    8 +++-----
 4 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 57d37d5..1e9ff56 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -32,14 +32,15 @@ typedef u32 kprobe_opcode_t;
 
 struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
-
 typedef unsigned long (kprobe_check_cc)(unsigned long);
+typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
 
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
-	kprobe_opcode_t		*insn;
-	kprobe_insn_handler_t	*insn_handler;
-	kprobe_check_cc		*insn_check_cc;
+	kprobe_opcode_t			*insn;
+	kprobe_insn_handler_t		*insn_handler;
+	kprobe_check_cc			*insn_check_cc;
+	kprobe_insn_singlestep_t	*insn_singlestep;
 };
 
 struct prev_kprobe {
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index 0262b29..a1143e8 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -1494,6 +1494,12 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 	return INSN_REJECTED;
 }
 
+static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 4;
+	p->ainsn.insn_handler(p, regs);
+}
+
 /* Return:
  *   INSN_REJECTED     If instruction is one not allowed to kprobe,
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
@@ -1509,6 +1515,7 @@ space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 enum kprobe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_singlestep = arm_singlestep;
 	asi->insn_check_cc = kprobe_condition_checks[insn>>28];
 	asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
 
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 24a188b..973c3eb 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -33,9 +33,24 @@ static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
 	return true;
 }
 
+static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 2;
+	p->ainsn.insn_handler(p, regs);
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
+static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 4;
+	p->ainsn.insn_handler(p, regs);
+	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+}
+
 enum kprobe_insn __kprobes
 thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_singlestep = thumb16_singlestep;
 	asi->insn_check_cc = thumb_check_cc;
 	return INSN_REJECTED;
 }
@@ -43,6 +58,7 @@ thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 enum kprobe_insn __kprobes
 thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_singlestep = thumb32_singlestep;
 	asi->insn_check_cc = thumb_check_cc;
 	return INSN_REJECTED;
 }
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 9104b03..3c5ed77 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -227,12 +227,10 @@ singlestep_skip(struct kprobe *p, struct pt_regs *regs)
 #endif
 }
 
-static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
-				 struct kprobe_ctlblk *kcb)
+static inline void __kprobes
+singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
-	regs->ARM_pc += 4;
-	if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
-		p->ainsn.insn_handler(p, regs);
+	p->ainsn.insn_singlestep(p, regs);
 }
 
 /*
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (16 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 17/51] ARM: kprobes: Add hooks to override singlestep() Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-11 19:19   ` Nicolas Pitre
  2011-07-09 10:57 ` [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions Tixy
                   ` (33 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

When we come to emulating Thumb instructions then, to interwork
correctly, the code on in the instruction slot must be invoked with a
function pointer which has the least significant bit set. Rather that
set this by hand in every Thumb emulation function we will add a new
field for this purpose to arch_specific_insn, called insn_fn.

This also enables us to seamlessly share emulation functions between ARM
and Thumb code.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/include/asm/kprobes.h |    2 ++
 arch/arm/kernel/kprobes.c      |    5 +++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 1e9ff56..feec867 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -34,6 +34,7 @@ struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
 typedef unsigned long (kprobe_check_cc)(unsigned long);
 typedef void (kprobe_insn_singlestep_t)(struct kprobe *, struct pt_regs *);
+typedef void (kprobe_insn_fn_t)(void);
 
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
@@ -41,6 +42,7 @@ struct arch_specific_insn {
 	kprobe_insn_handler_t		*insn_handler;
 	kprobe_check_cc			*insn_check_cc;
 	kprobe_insn_singlestep_t	*insn_singlestep;
+	kprobe_insn_fn_t		*insn_fn;
 };
 
 struct prev_kprobe {
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 3c5ed77..2de3a08 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -51,6 +51,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	kprobe_opcode_t insn;
 	kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
 	unsigned long addr = (unsigned long)p->addr;
+	bool thumb;
 	kprobe_decode_insn_t *decode_insn;
 	int is;
 
@@ -58,6 +59,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 		return -EINVAL;
 
 #ifdef CONFIG_THUMB2_KERNEL
+	thumb = 1;
 	addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
 	insn = ((u16 *)addr)[0];
 	if (is_wide_instruction(insn)) {
@@ -67,6 +69,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 	} else
 		decode_insn = thumb16_kprobe_decode_insn;
 #else /* !CONFIG_THUMB2_KERNEL */
+	thumb = 0;
 	if (addr & 0x3)
 		return -EINVAL;
 	insn = *p->addr;
@@ -88,6 +91,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
 			p->ainsn.insn[is] = tmp_insn[is];
 		flush_insns(p->ainsn.insn,
 				sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE);
+		p->ainsn.insn_fn = (kprobe_insn_fn_t *)
+					((uintptr_t)p->ainsn.insn | thumb);
 		break;
 
 	case INSN_GOOD_NO_SLOT:	/* instruction doesn't need insn slot */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (17 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-11 20:05   ` Nicolas Pitre
  2011-07-09 10:57 ` [PATCH 20/51] ARM: kprobes: Decode 16-bit Thumb hint instructions Tixy
                   ` (32 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The existing ARM instruction decoding functions are a mass of if/else
code. Rather than follow this pattern for Thumb instruction decoding
this patch implements an infrastructure for a new table driven scheme.

This has several advantages:

- Reduces the kernel size by approx 2kB. (The ARM instruction decoding
  will eventually have -3.1kB code, +1.3kB data; with similar or better
  estimated savings for Thumb decoding.)

- Allows programmatic checking of decoding consistency and test case
  coverage.

- Provides more uniform source code and is therefore, arguably, clearer.

For a detailed explanation of how decoding tables work see the in-source
documentation in kprobes.h, and also for kprobe_decode_insn().

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |  248 ++++++++++++++++++++++++++++++++++++-
 arch/arm/kernel/kprobes-common.c |  258 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 505 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index e3803c6..c00681c 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -1,7 +1,9 @@
 /*
  * arch/arm/kernel/kprobes.h
  *
- * Contents moved from arch/arm/include/asm/kprobes.h which is
+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.
+ *
+ * Some contents moved here from arch/arm/include/asm/kprobes.h which is
  * Copyright (C) 2006, 2007 Motorola Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -99,4 +101,248 @@ static inline unsigned long it_advance(unsigned long cpsr)
  */
 #define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
 
+/*
+ * The following definitions and macros are used to build instruction
+ * decoding tables for use by kprobe_decode_insn.
+ *
+ * These tables are a concatenation of entries each of which consist of one of
+ * the decode_* structs. All of the fields in every type of decode structure
+ * are of the union type decode_item, therefore the entire decode table can be
+ * viewed as an array of these and declared like:
+ *
+ *	static const union decode_item table_name[] = {};
+ *
+ * In order to construct each entry in the table, macros are used to
+ * initialise a number of sequential decode_item values in a layout which
+ * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct
+ * decode_simulate by initialising four decode_item objects like this...
+ *
+ *	{.bits = _type},
+ *	{.bits = _mask},
+ *	{.bits = _value},
+ *	{.handler = _handler},
+ *
+ * Initialising a specified member of the union means that the compiler
+ * will produce a warning if the argument is of an incorrect type.
+ *
+ * Below is a list of each of the macros used to initialise entries and a
+ * description of the action performed when that entry is matched to an
+ * instruction. A match is found when (instruction & mask) == value.
+ *
+ * DECODE_TABLE(mask, value, table)
+ *	Instruction decoding jumps to parsing the new sub-table 'table'.
+ *
+ * DECODE_CUSTOM(mask, value, decoder)
+ *	The custom function 'decoder' is called to the complete decoding
+ *	of an instruction.
+ *
+ * DECODE_SIMULATE(mask, value, handler)
+ *	Set the probes instruction handler to 'handler', this will be used
+ *	to simulate the instruction when the probe is hit. Decoding returns
+ *	with INSN_GOOD_NO_SLOT.
+ *
+ * DECODE_EMULATE(mask, value, handler)
+ *	Set the probes instruction handler to 'handler', this will be used
+ *	to emulate the instruction when the probe is hit. The modified
+ *	instruction (see below) is placed in the probes instruction slot so it
+ *	may be called by the emulation code. Decoding returns with INSN_GOOD.
+ *
+ * DECODE_REJECT(mask, value)
+ *	Instruction decoding fails with INSN_REJECTED
+ *
+ * DECODE_OR(mask, value)
+ *	This allows the mask/value test of multiple table entries to be
+ *	logically ORed. Once an 'or' entry is matched the decoding action to
+ *	be performed is that of the next entry which isn't an 'or'. E.g.
+ *
+ *		DECODE_OR	(mask1, value1)
+ *		DECODE_OR	(mask2, value2)
+ *		DECODE_SIMULATE	(mask3, value3, simulation_handler)
+ *
+ *	This means that if any of the three mask/value pairs match the
+ *	instruction being decoded, then 'simulation_handler' will be used
+ *	for it.
+ *
+ * Both the SIMULATE and EMULATE macros have a second form which take an
+ * additional 'regs' argument.
+ *
+ *	DECODE_SIMULATEX(mask, value, handler, regs)
+ *	DECODE_EMULATEX	(mask, value, handler, regs)
+ *
+ * These are used to specify what kind of CPU register is encoded in each of the
+ * least significant 5 nibbles of the instruction being decoded. The regs value
+ * is specified using the REGS macro, this takes any of the REG_TYPE_* values
+ * from enum decode_reg_type as arguments; only the '*' part of the name is
+ * given. E.g.
+ *
+ *	REGS(0, ANY, NOPC, 0, ANY)
+ *
+ * This indicates an instruction is encoded like:
+ *
+ *	bits 19..16	ignore
+ *	bits 15..12	any register allowed here
+ *	bits 11.. 8	any register except PC allowed here
+ *	bits  7.. 4	ignore
+ *	bits  3.. 0	any register allowed here
+ *
+ * This register specification is checked after a decode table entry is found to
+ * match an instruction (through the mask/value test). Any invalid register then
+ * found in the instruction will cause decoding to fail with INSN_REJECTED. In
+ * the above example this would happen if bits 11..8 of the instruction were
+ * 1111, indicating R15 or PC.
+ *
+ * As well as checking for legal combinations of registers, this data is also
+ * used to modify the registers encoded in the instructions so that an
+ * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.)
+ *
+ * Here is a real example which matches ARM instructions of the form
+ * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>"
+ *
+ *	DECODE_EMULATEX	(0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags,
+ *						 REGS(ANY, ANY, NOPC, 0, ANY)),
+ *						      ^    ^    ^        ^
+ *						      Rn   Rd   Rs       Rm
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because
+ * Rs == R15
+ *
+ * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the
+ * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into
+ * the kprobes instruction slot. This can then be called later by the handler
+ * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction.
+ */
+
+enum decode_type {
+	DECODE_TYPE_END,
+	DECODE_TYPE_TABLE,
+	DECODE_TYPE_CUSTOM,
+	DECODE_TYPE_SIMULATE,
+	DECODE_TYPE_EMULATE,
+	DECODE_TYPE_OR,
+	DECODE_TYPE_REJECT,
+	NUM_DECODE_TYPES /* Must be last enum */
+};
+
+#define DECODE_TYPE_BITS	4
+#define DECODE_TYPE_MASK	((1 << DECODE_TYPE_BITS) - 1)
+
+enum decode_reg_type {
+	REG_TYPE_NONE = 0, /* Not a register, ignore */
+	REG_TYPE_ANY,	   /* Any register allowed */
+	REG_TYPE_SAMEAS16, /* Register should be same as that@bits 19..16 */
+	REG_TYPE_SP,	   /* Register must be SP */
+	REG_TYPE_PC,	   /* Register must be PC */
+	REG_TYPE_NOSP,	   /* Register must not be SP */
+	REG_TYPE_NOSPPC,   /* Register must not be SP or PC */
+	REG_TYPE_NOPC,	   /* Register must not be PC */
+	REG_TYPE_NOPCWB,   /* No PC if load/store write-back flag also set */
+
+	/* The following types are used when the encoding for PC indicates
+	 * another instruction form. This distiction only matters for test
+	 * case coverage checks.
+	 */
+	REG_TYPE_NOPCX,	   /* Register must not be PC */
+	REG_TYPE_NOSPPCX,  /* Register must not be SP or PC */
+
+	/* Alias to allow '0' arg to be used in REGS macro. */
+	REG_TYPE_0 = REG_TYPE_NONE
+};
+
+#define REGS(r16, r12, r8, r4, r0)	\
+	((REG_TYPE_##r16) << 16) +	\
+	((REG_TYPE_##r12) << 12) +	\
+	((REG_TYPE_##r8) << 8) +	\
+	((REG_TYPE_##r4) << 4) +	\
+	(REG_TYPE_##r0)
+
+union decode_item {
+	u32			bits;
+	const union decode_item	*table;
+	kprobe_insn_handler_t	*handler;
+	kprobe_decode_insn_t	*decoder;
+};
+
+
+#define DECODE_END			\
+	{.bits = DECODE_TYPE_END}
+
+
+struct decode_header {
+	union decode_item	type_regs;
+	union decode_item	mask;
+	union decode_item	value;
+};
+
+#define DECODE_HEADER(_type, _mask, _value, _regs)		\
+	{.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)},	\
+	{.bits = (_mask)},					\
+	{.bits = (_value)}
+
+
+struct decode_table {
+	struct decode_header	header;
+	union decode_item	table;
+};
+
+#define DECODE_TABLE(_mask, _value, _table)			\
+	DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0),	\
+	{.table = (_table)}
+
+
+struct decode_custom {
+	struct decode_header	header;
+	union decode_item	decoder;
+};
+
+#define DECODE_CUSTOM(_mask, _value, _decoder)			\
+	DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0),	\
+	{.decoder = (_decoder)}
+
+
+struct decode_simulate {
+	struct decode_header	header;
+	union decode_item	handler;
+};
+
+#define DECODE_SIMULATEX(_mask, _value, _handler, _regs)		\
+	DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs),	\
+	{.handler = (_handler)}
+
+#define DECODE_SIMULATE(_mask, _value, _handler)	\
+	DECODE_SIMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_emulate {
+	struct decode_header	header;
+	union decode_item	handler;
+};
+
+#define DECODE_EMULATEX(_mask, _value, _handler, _regs)			\
+	DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs),	\
+	{.handler = (_handler)}
+
+#define DECODE_EMULATE(_mask, _value, _handler)		\
+	DECODE_EMULATEX(_mask, _value, _handler, 0)
+
+
+struct decode_or {
+	struct decode_header	header;
+};
+
+#define DECODE_OR(_mask, _value)				\
+	DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
+
+
+struct decode_reject {
+	struct decode_header	header;
+};
+
+#define DECODE_REJECT(_mask, _value)				\
+	DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
+
+
+int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+			const union decode_item *table, bool thumb16);
+
+
 #endif /* _ARM_KERNEL_KPROBES_H */
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 87e91ce..4074806 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -140,3 +140,261 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
 	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
 	&__check_gt, &__check_le, &__check_al, &__check_al
 };
+
+
+/*
+ * Prepare an instruction slot to receive an instruction for emulating.
+ * This is done by placing a subroutine return after the location where the
+ * instruction will be placed. We also modify ARM instructions to be
+ * unconditional as the condition code will already be checked before any
+ * emulation handler is called.
+ */
+static kprobe_opcode_t __kprobes
+prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+								bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if (thumb) {
+		u16* thumb_insn = (u16 *)asi->insn;
+		thumb_insn[1] = 0x4770; /* Thumb bx lr */
+		thumb_insn[2] = 0x4770; /* Thumb bx lr */
+		return insn;
+	}
+	asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
+#else
+	asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
+#endif
+	/* Make an ARM instructional unconditional */
+	if (insn < 0xe0000000)
+		insn = (insn | 0xe0000000) & ~0x10000000;
+	return insn;
+}
+
+/*
+ * Write a (probably modified) instruction into the slot previously prepared by
+ * prepare_emulated_insn
+ */
+static void  __kprobes
+set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+								bool thumb)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+	if (thumb) {
+		u16 *ip = (u16 *)asi->insn;
+		if (is_wide_instruction(insn))
+			*ip++ = insn >> 16;
+		*ip++ = insn;
+		return;
+	}
+#endif
+	asi->insn[0] = insn;
+}
+
+/*
+ * When we modify the register numbers encoded in an instruction to be emulated,
+ * the new values come from this define. For ARM and 32-bit Thumb instructions
+ * this gives...
+ *
+ *	bit position	  16  12   8   4   0
+ *	---------------+---+---+---+---+---+
+ *	register	 r2  r0  r1  --  r3
+ */
+#define INSN_NEW_BITS		0x00020103
+
+/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */
+#define INSN_SAMEAS16_BITS	0x22222222
+
+/*
+ * Validate and modify each of the registers encoded in an instruction.
+ *
+ * Each nibble in regs contains a value from enum decode_reg_type. For each
+ * non-zero value, the corresponding nibble in pinsn is validated and modified
+ * according to the type.
+ */
+static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs)
+{
+	kprobe_opcode_t insn = *pinsn;
+	kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */
+
+	for (; regs != 0; regs >>= 4, mask <<= 4) {
+
+		kprobe_opcode_t new_bits = INSN_NEW_BITS;
+
+		switch (regs & 0xf) {
+
+		case REG_TYPE_NONE:
+			/* Nibble not a register, skip to next */
+			continue;
+
+		case REG_TYPE_ANY:
+			/* Any register is allowed */
+			break;
+
+		case REG_TYPE_SAMEAS16:
+			/* Replace register with same as@bit position 16 */
+			new_bits = INSN_SAMEAS16_BITS;
+			break;
+
+		case REG_TYPE_SP:
+			/* Only allow SP (R13) */
+			if ((insn ^ 0xdddddddd) & mask)
+				goto reject;
+			break;
+
+		case REG_TYPE_PC:
+			/* Only allow PC (R15) */
+			if ((insn ^ 0xffffffff) & mask)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOSP:
+			/* Reject SP (R13) */
+			if (((insn ^ 0xdddddddd) & mask) == 0)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOSPPC:
+		case REG_TYPE_NOSPPCX:
+			/* Reject SP and PC (R13 and R15) */
+			if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0)
+				goto reject;
+			break;
+
+		case REG_TYPE_NOPCWB:
+			if (!is_writeback(insn))
+				break; /* No writeback, so any register is OK */
+			/* fall through... */
+		case REG_TYPE_NOPC:
+		case REG_TYPE_NOPCX:
+			/* Reject PC (R15) */
+			if (((insn ^ 0xffffffff) & mask) == 0)
+				goto reject;
+			break;
+		}
+
+		/* Replace value of nibble with new register number... */
+		insn &= ~mask;
+		insn |= new_bits & mask;
+	}
+
+	*pinsn = insn;
+	return true;
+
+reject:
+	return false;
+}
+
+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {
+	[DECODE_TYPE_TABLE]	= sizeof(struct decode_table),
+	[DECODE_TYPE_CUSTOM]	= sizeof(struct decode_custom),
+	[DECODE_TYPE_SIMULATE]	= sizeof(struct decode_simulate),
+	[DECODE_TYPE_EMULATE]	= sizeof(struct decode_emulate),
+	[DECODE_TYPE_OR]	= sizeof(struct decode_or),
+	[DECODE_TYPE_REJECT]	= sizeof(struct decode_reject)
+};
+
+/*
+ * kprobe_decode_insn operates on data tables in order to decode an ARM
+ * architecture instruction onto which a kprobe has been placed.
+ *
+ * These instruction decoding tables are a concatenation of entries each
+ * of which consist of one of the following structs:
+ *
+ *	decode_table
+ *	decode_custom
+ *	decode_simulate
+ *	decode_emulate
+ *	decode_or
+ *	decode_reject
+ *
+ * Each of these starts with a struct decode_header which has the following
+ * fields:
+ *
+ *	type_regs
+ *	mask
+ *	value
+ *
+ * The least significant DECODE_TYPE_BITS of type_regs contains a value
+ * from enum decode_type, this indicates which of the decode_* structs
+ * the entry contains. The value DECODE_TYPE_END indicates the end of the
+ * table.
+ *
+ * When the table is parsed, each entry is checked in turn to see if it
+ * matches the instruction to be decoded using the test:
+ *
+ *	(insn & mask) == value
+ *
+ * If no match is found before the end of the table is reached then decoding
+ * fails with INSN_REJECTED.
+ *
+ * When a match is found, decode_regs() is called to validate and modify each
+ * of the registers encoded in the instruction; the data it uses to do this
+ * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding
+ * to fail with INSN_REJECTED.
+ *
+ * Once the instruction has passed the above tests, further processing
+ * depends on the type of the table entry's decode struct.
+ *
+ */
+int __kprobes
+kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
+				const union decode_item *table, bool thumb)
+{
+	const struct decode_header *h = (struct decode_header *)table;
+	const struct decode_header *next;
+	bool matched = false;
+
+	insn = prepare_emulated_insn(insn, asi, thumb);
+
+	for (;; h = next) {
+		enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;
+		u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS;
+
+		if (type == DECODE_TYPE_END)
+			return INSN_REJECTED;
+
+		next = (struct decode_header *)
+				((uintptr_t)h + decode_struct_sizes[type]);
+
+		if (!matched && (insn & h->mask.bits) != h->value.bits)
+			continue;
+
+		if (!decode_regs(&insn, regs))
+			return INSN_REJECTED;
+
+		switch (type) {
+
+		case DECODE_TYPE_TABLE: {
+			struct decode_table *d = (struct decode_table *)h;
+			next = (struct decode_header *)d->table.table;
+			break;
+		}
+
+		case DECODE_TYPE_CUSTOM: {
+			struct decode_custom *d = (struct decode_custom *)h;
+			return (*d->decoder.decoder)(insn, asi);
+		}
+
+		case DECODE_TYPE_SIMULATE: {
+			struct decode_simulate *d = (struct decode_simulate *)h;
+			asi->insn_handler = d->handler.handler;
+			return INSN_GOOD_NO_SLOT;
+		}
+
+		case DECODE_TYPE_EMULATE: {
+			struct decode_emulate *d = (struct decode_emulate *)h;
+			asi->insn_handler = d->handler.handler;
+			set_emulated_insn(insn, asi, thumb);
+			return INSN_GOOD;
+		}
+
+		case DECODE_TYPE_OR:
+			matched = true;
+			break;
+
+		case DECODE_TYPE_REJECT:
+		default:
+			return INSN_REJECTED;
+		}
+		}
+	}
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 20/51] ARM: kprobes: Decode 16-bit Thumb hint instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (18 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 21/51] ARM: ptrace: Add APSR_MASK definition to ptrace.h Tixy
                   ` (31 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

For hints which may have observable effects, like SEV (send event), we
use kprobe_emulate_none which emulates the hint by executing the
original instruction.

For NOP we simulate the instruction using kprobe_simulate_nop, which
does nothing. As probes execute with interrupts disabled this is also
used for hints which may block for an indefinite time, like WFE (wait
for event).

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |    3 +++
 arch/arm/kernel/kprobes-common.c |    9 +++++++++
 arch/arm/kernel/kprobes-thumb.c  |   35 ++++++++++++++++++++++++++++++++++-
 3 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index c00681c..36e0768 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -95,6 +95,9 @@ static inline unsigned long it_advance(unsigned long cpsr)
 	return cpsr;
 }
 
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
+
 /*
  * Test if load/store instructions writeback the address register.
  * if P (bit 24) == 0 or W (bit 21) == 1
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 4074806..84c0c74 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -142,6 +142,15 @@ kprobe_check_cc * const kprobe_condition_checks[16] = {
 };
 
 
+void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs)
+{
+}
+
+void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
+{
+	p->ainsn.insn_fn();
+}
+
 /*
  * Prepare an instruction slot to receive an instruction for emulating.
  * This is done by placing a subroutine return after the location where the
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 973c3eb..7dcf6df 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -26,6 +26,39 @@
  */
 #define current_cond(cpsr)	((cpsr >> 12) & 0xf)
 
+static const union decode_item t16_table_1011[] = {
+	/* Miscellaneous 16-bit instructions		    */
+
+	/*
+	 * If-Then, and hints
+	 *				1011 1111 xxxx xxxx
+	 */
+
+	/* YIELD			1011 1111 0001 0000 */
+	DECODE_OR	(0xffff, 0xbf10),
+	/* SEV				1011 1111 0100 0000 */
+	DECODE_EMULATE	(0xffff, 0xbf40, kprobe_emulate_none),
+	/* NOP				1011 1111 0000 0000 */
+	/* WFE				1011 1111 0010 0000 */
+	/* WFI				1011 1111 0011 0000 */
+	DECODE_SIMULATE	(0xffcf, 0xbf00, kprobe_simulate_nop),
+	/* Unassigned hints		1011 1111 xxxx 0000 */
+	DECODE_REJECT	(0xff0f, 0xbf00),
+
+	DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb16_table[] = {
+
+	/*
+	 * Miscellaneous 16-bit instructions
+	 *				1011 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xf000, 0xb000, t16_table_1011),
+
+	DECODE_END
+};
+
 static unsigned long __kprobes thumb_check_cc(unsigned long cpsr)
 {
 	if (unlikely(in_it_block(cpsr)))
@@ -52,7 +85,7 @@ thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
 	asi->insn_singlestep = thumb16_singlestep;
 	asi->insn_check_cc = thumb_check_cc;
-	return INSN_REJECTED;
+	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true);
 }
 
 enum kprobe_insn __kprobes
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 21/51] ARM: ptrace: Add APSR_MASK definition to ptrace.h
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (19 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 20/51] ARM: kprobes: Decode 16-bit Thumb hint instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 22/51] ARM: kprobes: Decode 16-bit Thumb data-processing instructions Tixy
                   ` (30 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

APSR_MASK can be used to extract the APSR bits from the CPSR. The
comment for these definitions is also changed because it was inaccurate
as the existing defines didn't refer to any part of the APSR.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/include/asm/ptrace.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index d484871..96187ff 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -69,8 +69,9 @@
 #define PSR_c		0x000000ff	/* Control		*/
 
 /*
- * ARMv7 groups of APSR bits
+ * ARMv7 groups of PSR bits
  */
+#define APSR_MASK	0xf80f0000	/* N, Z, C, V, Q and GE flags */
 #define PSR_ISET_MASK	0x01000010	/* ISA state (J, T) mask */
 #define PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
 #define PSR_ENDIAN_MASK	0x00000200	/* Endianness state mask */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 22/51] ARM: kprobes: Decode 16-bit Thumb data-processing instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (20 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 21/51] ARM: ptrace: Add APSR_MASK definition to ptrace.h Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 23/51] ARM: kprobes: Add bx_write_pc() Tixy
                   ` (29 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

These instructions only operate on the low registers R0-R7, therefore
it is possible to emulate them by executing the original instruction
unaltered if we restore and save these registers. This is what
t16_emulate_loregs does.

Some of these instructions don't update the PSR when they execute in an
IT block, so there are two flavours of emulation functions:
t16_emulate_loregs_{noit}rwflags

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   81 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 81 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 7dcf6df..e1cef82 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -26,6 +26,42 @@
  */
 #define current_cond(cpsr)	((cpsr >> 12) & 0xf)
 
+static unsigned long __kprobes
+t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long oldcpsr = regs->ARM_cpsr;
+	unsigned long newcpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[oldcpsr]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"mrs	%[newcpsr], cpsr	\n\t"
+		: [newcpsr] "=r" (newcpsr)
+		: [oldcpsr] "r" (oldcpsr), [regs] "r" (regs),
+		  [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+		  "lr", "memory", "cc"
+		);
+
+	return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK);
+}
+
+static void __kprobes
+t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_cpsr = t16_emulate_loregs(p, regs);
+}
+
+static void __kprobes
+t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long cpsr = t16_emulate_loregs(p, regs);
+	if (!in_it_block(cpsr))
+		regs->ARM_cpsr = cpsr;
+}
+
 static const union decode_item t16_table_1011[] = {
 	/* Miscellaneous 16-bit instructions		    */
 
@@ -51,6 +87,51 @@ static const union decode_item t16_table_1011[] = {
 const union decode_item kprobe_decode_thumb16_table[] = {
 
 	/*
+	 * Shift (immediate), add, subtract, move, and compare
+	 *				00xx xxxx xxxx xxxx
+	 */
+
+	/* CMP (immediate)		0010 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf800, 0x2800, t16_emulate_loregs_rwflags),
+
+	/* ADD (register)		0001 100x xxxx xxxx */
+	/* SUB (register)		0001 101x xxxx xxxx */
+	/* LSL (immediate)		0000 0xxx xxxx xxxx */
+	/* LSR (immediate)		0000 1xxx xxxx xxxx */
+	/* ASR (immediate)		0001 0xxx xxxx xxxx */
+	/* ADD (immediate, Thumb)	0001 110x xxxx xxxx */
+	/* SUB (immediate, Thumb)	0001 111x xxxx xxxx */
+	/* MOV (immediate)		0010 0xxx xxxx xxxx */
+	/* ADD (immediate, Thumb)	0011 0xxx xxxx xxxx */
+	/* SUB (immediate, Thumb)	0011 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xc000, 0x0000, t16_emulate_loregs_noitrwflags),
+
+	/*
+	 * 16-bit Thumb data-processing instructions
+	 *				0100 00xx xxxx xxxx
+	 */
+
+	/* TST (register)		0100 0010 00xx xxxx */
+	DECODE_EMULATE	(0xffc0, 0x4200, t16_emulate_loregs_rwflags),
+	/* CMP (register)		0100 0010 10xx xxxx */
+	/* CMN (register)		0100 0010 11xx xxxx */
+	DECODE_EMULATE	(0xff80, 0x4280, t16_emulate_loregs_rwflags),
+	/* AND (register)		0100 0000 00xx xxxx */
+	/* EOR (register)		0100 0000 01xx xxxx */
+	/* LSL (register)		0100 0000 10xx xxxx */
+	/* LSR (register)		0100 0000 11xx xxxx */
+	/* ASR (register)		0100 0001 00xx xxxx */
+	/* ADC (register)		0100 0001 01xx xxxx */
+	/* SBC (register)		0100 0001 10xx xxxx */
+	/* ROR (register)		0100 0001 11xx xxxx */
+	/* RSB (immediate)		0100 0010 01xx xxxx */
+	/* ORR (register)		0100 0011 00xx xxxx */
+	/* MUL				0100 0011 00xx xxxx */
+	/* BIC (register)		0100 0011 10xx xxxx */
+	/* MVN (register)		0100 0011 10xx xxxx */
+	DECODE_EMULATE	(0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
+
+	/*
 	 * Miscellaneous 16-bit instructions
 	 *				1011 xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 23/51] ARM: kprobes: Add bx_write_pc()
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (21 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 22/51] ARM: kprobes: Decode 16-bit Thumb data-processing instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 24/51] ARM: kprobes: Decode 16-bit Thumb BX and BLX instructions Tixy
                   ` (28 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This writes a value to PC, with interworking. I.e. switches to Thumb or
ARM mode depending on the state of the least significant bit.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 36e0768..12627a3 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -95,6 +95,20 @@ static inline unsigned long it_advance(unsigned long cpsr)
 	return cpsr;
 }
 
+static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
+{
+	long cpsr = regs->ARM_cpsr;
+	if (pcv & 0x1) {
+		cpsr |= PSR_T_BIT;
+		pcv &= ~0x1;
+	} else {
+		cpsr &= ~PSR_T_BIT;
+		pcv &= ~0x2;	/* Avoid UNPREDICTABLE address allignment */
+	}
+	regs->ARM_cpsr = cpsr;
+	regs->ARM_pc = pcv;
+}
+
 void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
 void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 24/51] ARM: kprobes: Decode 16-bit Thumb BX and BLX instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (22 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 23/51] ARM: kprobes: Add bx_write_pc() Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 25/51] ARM: kprobes: Decode 16-bit Thumb special data instructions Tixy
                   ` (27 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index e1cef82..b457da0 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -26,6 +26,31 @@
  */
 #define current_cond(cpsr)	((cpsr >> 12) & 0xf)
 
+/*
+ * Return the PC value for a probe in thumb code.
+ * This is the address of the probed instruction plus 4.
+ * We subtract one because the address will have bit zero set to indicate
+ * a pointer to thumb code.
+ */
+static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
+{
+	return (unsigned long)p->addr - 1 + 4;
+}
+
+static void __kprobes
+t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rm = (insn >> 3) & 0xf;
+	unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+	if (insn & (1 << 7)) /* BLX ? */
+		regs->ARM_lr = (unsigned long)p->addr + 2;
+
+	bx_write_pc(rmv, regs);
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -132,6 +157,18 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	DECODE_EMULATE	(0xfc00, 0x4000, t16_emulate_loregs_noitrwflags),
 
 	/*
+	 * Special data instructions and branch and exchange
+	 *				0100 01xx xxxx xxxx
+	 */
+
+	/* BLX pc			0100 0111 1111 1xxx */
+	DECODE_REJECT	(0xfff8, 0x47f8),
+
+	/* BX (register)		0100 0111 0xxx xxxx */
+	/* BLX (register)		0100 0111 1xxx xxxx */
+	DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
+
+	/*
 	 * Miscellaneous 16-bit instructions
 	 *				1011 xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 25/51] ARM: kprobes: Decode 16-bit Thumb special data instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (23 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 24/51] ARM: kprobes: Decode 16-bit Thumb BX and BLX instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 26/51] ARM: kprobes: Decode 16-bit Thumb load and store instructions Tixy
                   ` (26 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

These data-processing instructions operate on the full range of CPU
registers, so to simulate them we have to modify the registers used
by the instruction. We can't make use of the decoding table framework to
do this because the registers aren't encoded cleanly in separate
nibbles, therefore we need a custom decode function.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   49 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index b457da0..cd4d03d 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -87,6 +87,47 @@ t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs)
 		regs->ARM_cpsr = cpsr;
 }
 
+static void __kprobes
+t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rdn = (insn & 0x7) | ((insn & 0x80) >> 4);
+	int rm = (insn >> 3) & 0xf;
+
+	register unsigned long rdnv asm("r1");
+	register unsigned long rmv asm("r0");
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	rdnv = (rdn == 15) ? pc : regs->uregs[rdn];
+	rmv = (rm == 15) ? pc : regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		"blx    %[fn]			\n\t"
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdnv), [cpsr] "=r" (cpsr)
+		: "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rdn == 15)
+		rdnv &= ~1;
+
+	regs->uregs[rdn] = rdnv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	insn &= ~0x00ff;
+	insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
+	((u16 *)asi->insn)[0] = insn;
+	asi->insn_handler = t16_emulate_hiregs;
+	return INSN_GOOD;
+}
+
 static const union decode_item t16_table_1011[] = {
 	/* Miscellaneous 16-bit instructions		    */
 
@@ -168,6 +209,14 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	/* BLX (register)		0100 0111 1xxx xxxx */
 	DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx),
 
+	/* ADD pc, pc			0100 0100 1111 1111 */
+	DECODE_REJECT	(0xffff, 0x44ff),
+
+	/* ADD (register)		0100 0100 xxxx xxxx */
+	/* CMP (register)		0100 0101 xxxx xxxx */
+	/* MOV (register)		0100 0110 xxxx xxxx */
+	DECODE_CUSTOM	(0xfc00, 0x4400, t16_decode_hiregs),
+
 	/*
 	 * Miscellaneous 16-bit instructions
 	 *				1011 xxxx xxxx xxxx
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 26/51] ARM: kprobes: Decode 16-bit Thumb load and store instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (24 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 25/51] ARM: kprobes: Decode 16-bit Thumb special data instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 27/51] ARM: kprobes: Decode 16-bit Thumb PC- and SP-relative address instructions Tixy
                   ` (25 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Most of these instructions only operate on the low registers R0-R7
so they can make use of t16_emulate_loregs_rwflags.

The instructions which use SP or PC for addressing have their own
simulation functions.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   60 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index cd4d03d..632a5e8 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -51,6 +51,29 @@ t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
 	bx_write_pc(rmv, regs);
 }
 
+static void __kprobes
+t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3);
+	long index = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	regs->uregs[rt] = base[index];
+}
+
+static void __kprobes
+t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long* base = (unsigned long *)regs->ARM_sp;
+	long index = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	if (insn & 0x800) /* LDR */
+		regs->uregs[rt] = base[index];
+	else /* STR */
+		base[index] = regs->uregs[rt];
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -218,11 +241,48 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	DECODE_CUSTOM	(0xfc00, 0x4400, t16_decode_hiregs),
 
 	/*
+	 * Load from Literal Pool
+	 * LDR (literal)		0100 1xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf800, 0x4800, t16_simulate_ldr_literal),
+
+	/*
+	 * 16-bit Thumb Load/store instructions
+	 *				0101 xxxx xxxx xxxx
+	 *				011x xxxx xxxx xxxx
+	 *				100x xxxx xxxx xxxx
+	 */
+
+	/* STR (register)		0101 000x xxxx xxxx */
+	/* STRH (register)		0101 001x xxxx xxxx */
+	/* STRB (register)		0101 010x xxxx xxxx */
+	/* LDRSB (register)		0101 011x xxxx xxxx */
+	/* LDR (register)		0101 100x xxxx xxxx */
+	/* LDRH (register)		0101 101x xxxx xxxx */
+	/* LDRB (register)		0101 110x xxxx xxxx */
+	/* LDRSH (register)		0101 111x xxxx xxxx */
+	/* STR (immediate, Thumb)	0110 0xxx xxxx xxxx */
+	/* LDR (immediate, Thumb)	0110 1xxx xxxx xxxx */
+	/* STRB (immediate, Thumb)	0111 0xxx xxxx xxxx */
+	/* LDRB (immediate, Thumb)	0111 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xc000, 0x4000, t16_emulate_loregs_rwflags),
+	/* STRH (immediate, Thumb)	1000 0xxx xxxx xxxx */
+	/* LDRH (immediate, Thumb)	1000 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf000, 0x8000, t16_emulate_loregs_rwflags),
+	/* STR (immediate, Thumb)	1001 0xxx xxxx xxxx */
+	/* LDR (immediate, Thumb)	1001 1xxx xxxx xxxx */
+	DECODE_SIMULATE	(0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
+
+	/*
 	 * Miscellaneous 16-bit instructions
 	 *				1011 xxxx xxxx xxxx
 	 */
 	DECODE_TABLE	(0xf000, 0xb000, t16_table_1011),
 
+	/* STM				1100 0xxx xxxx xxxx */
+	/* LDM				1100 1xxx xxxx xxxx */
+	DECODE_EMULATE	(0xf000, 0xc000, t16_emulate_loregs_rwflags),
+
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 27/51] ARM: kprobes: Decode 16-bit Thumb PC- and SP-relative address instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (25 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 26/51] ARM: kprobes: Decode 16-bit Thumb load and store instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 28/51] ARM: kprobes: Decode 16-bit Thumb CBZ and bit manipulation instructions Tixy
                   ` (24 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 632a5e8..2b30828 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -74,6 +74,28 @@ t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs)
 		base[index] = regs->uregs[rt];
 }
 
+static void __kprobes
+t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long base = (insn & 0x800) ? regs->ARM_sp
+					    : (thumb_probe_pc(p) & ~3);
+	long offset = insn & 0xff;
+	int rt = (insn >> 8) & 0x7;
+	regs->uregs[rt] = base + offset * 4;
+}
+
+static void __kprobes
+t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	long imm = insn & 0x7f;
+	if (insn & 0x80) /* SUB */
+		regs->ARM_sp -= imm * 4;
+	else /* ADD */
+		regs->ARM_sp += imm * 4;
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -154,6 +176,10 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 static const union decode_item t16_table_1011[] = {
 	/* Miscellaneous 16-bit instructions		    */
 
+	/* ADD (SP plus immediate)	1011 0000 0xxx xxxx */
+	/* SUB (SP minus immediate)	1011 0000 1xxx xxxx */
+	DECODE_SIMULATE	(0xff00, 0xb000, t16_simulate_add_sp_imm),
+
 	/*
 	 * If-Then, and hints
 	 *				1011 1111 xxxx xxxx
@@ -274,6 +300,13 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	DECODE_SIMULATE	(0xf000, 0x9000, t16_simulate_ldrstr_sp_relative),
 
 	/*
+	 * Generate PC-/SP-relative address
+	 * ADR (literal)		1010 0xxx xxxx xxxx
+	 * ADD (SP plus immediate)	1010 1xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf000, 0xa000, t16_simulate_reladr),
+
+	/*
 	 * Miscellaneous 16-bit instructions
 	 *				1011 xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 28/51] ARM: kprobes: Decode 16-bit Thumb CBZ and bit manipulation instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (26 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 27/51] ARM: kprobes: Decode 16-bit Thumb PC- and SP-relative address instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 29/51] ARM: kprobes: Decode 16-bit Thumb PUSH and POP instructions Tixy
                   ` (23 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   29 +++++++++++++++++++++++++++++
 1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 2b30828..a5bdb2d 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -96,6 +96,20 @@ t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs)
 		regs->ARM_sp += imm * 4;
 }
 
+static void __kprobes
+t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rn = insn & 0x7;
+	kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn;
+	if (nonzero & 0x800) {
+		long i = insn & 0x200;
+		long imm5 = insn & 0xf8;
+		unsigned long pc = thumb_probe_pc(p);
+		regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2);
+	}
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -180,6 +194,21 @@ static const union decode_item t16_table_1011[] = {
 	/* SUB (SP minus immediate)	1011 0000 1xxx xxxx */
 	DECODE_SIMULATE	(0xff00, 0xb000, t16_simulate_add_sp_imm),
 
+	/* CBZ				1011 00x1 xxxx xxxx */
+	/* CBNZ				1011 10x1 xxxx xxxx */
+	DECODE_SIMULATE	(0xf500, 0xb100, t16_simulate_cbz),
+
+	/* SXTH				1011 0010 00xx xxxx */
+	/* SXTB				1011 0010 01xx xxxx */
+	/* UXTH				1011 0010 10xx xxxx */
+	/* UXTB				1011 0010 11xx xxxx */
+	/* REV				1011 1010 00xx xxxx */
+	/* REV16			1011 1010 01xx xxxx */
+	/* ???				1011 1010 10xx xxxx */
+	/* REVSH			1011 1010 11xx xxxx */
+	DECODE_REJECT	(0xffc0, 0xba80),
+	DECODE_EMULATE	(0xf500, 0xb000, t16_emulate_loregs_rwflags),
+
 	/*
 	 * If-Then, and hints
 	 *				1011 1111 xxxx xxxx
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 29/51] ARM: kprobes: Decode 16-bit Thumb PUSH and POP instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (27 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 28/51] ARM: kprobes: Decode 16-bit Thumb CBZ and bit manipulation instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 30/51] ARM: kprobes: Decode 16-bit Thumb IT instruction Tixy
                   ` (22 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

These instructions are equivalent to

	stmdb sp!,{r0-r7,lr}
	ldmdb sp!,{r0-r7,pc}

and we emulate them by transforming them into the 32-bit Thumb
instructions

	stmdb r9!,{r0-r7,r8}
	ldmdb r9!,{r0-r7,r8}

This is simpler, and almost certainly executes faster, than writing
simulation functions.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   86 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index a5bdb2d..e028949 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -187,6 +187,87 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 	return INSN_GOOD;
 }
 
+static void __kprobes
+t16_emulate_push(struct kprobe *p, struct pt_regs *regs)
+{
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldr	r8, [%[regs], #14*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		:
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+		  "lr", "memory", "cc"
+		);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	/*
+	 * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}"
+	 * and call it with R9=SP and LR in the register list represented
+	 * by R8.
+	 */
+	((u16 *)asi->insn)[0] = 0xe929;		/* 1st half STMDB R9!,{} */
+	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
+	asi->insn_handler = t16_emulate_push;
+	return INSN_GOOD;
+}
+
+static void __kprobes
+t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs)
+{
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		:
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+		  "lr", "memory", "cc"
+		);
+}
+
+static void __kprobes
+t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	register unsigned long pc asm("r8");
+
+	__asm__ __volatile__ (
+		"ldr	r9, [%[regs], #13*4]	\n\t"
+		"ldmia	%[regs], {r0-r7}	\n\t"
+		"blx	%[fn]			\n\t"
+		"stmia	%[regs], {r0-r7}	\n\t"
+		"str	r9, [%[regs], #13*4]	\n\t"
+		: "=r" (pc)
+		: [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn)
+		: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9",
+		  "lr", "memory", "cc"
+		);
+
+	bx_write_pc(pc, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	/*
+	 * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}"
+	 * and call it with R9=SP and PC in the register list represented
+	 * by R8.
+	 */
+	((u16 *)asi->insn)[0] = 0xe8b9;		/* 1st half LDMIA R9!,{} */
+	((u16 *)asi->insn)[1] = insn & 0x1ff;	/* 2nd half (register list) */
+	asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
+					 : t16_emulate_pop_nopc;
+	return INSN_GOOD;
+}
+
 static const union decode_item t16_table_1011[] = {
 	/* Miscellaneous 16-bit instructions		    */
 
@@ -209,6 +290,11 @@ static const union decode_item t16_table_1011[] = {
 	DECODE_REJECT	(0xffc0, 0xba80),
 	DECODE_EMULATE	(0xf500, 0xb000, t16_emulate_loregs_rwflags),
 
+	/* PUSH				1011 010x xxxx xxxx */
+	DECODE_CUSTOM	(0xfe00, 0xb400, t16_decode_push),
+	/* POP				1011 110x xxxx xxxx */
+	DECODE_CUSTOM	(0xfe00, 0xbc00, t16_decode_pop),
+
 	/*
 	 * If-Then, and hints
 	 *				1011 1111 xxxx xxxx
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 30/51] ARM: kprobes: Decode 16-bit Thumb IT instruction
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (28 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 29/51] ARM: kprobes: Decode 16-bit Thumb PUSH and POP instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 31/51] ARM: kprobes: Reject 16-bit Thumb SVC and UNDEFINED instructions Tixy
                   ` (21 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The normal Thumb singlestepping routine updates the IT state after
calling the instruction handler. We don't what this to happen after the
IT instruction simulation sets the IT state, therefore we need to
provide a custom singlestep routine.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index e028949..e496948 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -110,6 +110,37 @@ t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs)
 	}
 }
 
+static void __kprobes
+t16_simulate_it(struct kprobe *p, struct pt_regs *regs)
+{
+	/*
+	 * The 8 IT state bits are split into two parts in CPSR:
+	 *	ITSTATE<1:0> are in CPSR<26:25>
+	 *	ITSTATE<7:2> are in CPSR<15:10>
+	 * The new IT state is in the lower byte of insn.
+	 */
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long cpsr = regs->ARM_cpsr;
+	cpsr &= ~PSR_IT_MASK;
+	cpsr |= (insn & 0xfc) << 8;
+	cpsr |= (insn & 0x03) << 25;
+	regs->ARM_cpsr = cpsr;
+}
+
+static void __kprobes
+t16_singlestep_it(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc += 2;
+	t16_simulate_it(p, regs);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	asi->insn_singlestep = t16_singlestep_it;
+	return INSN_GOOD_NO_SLOT;
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -310,6 +341,8 @@ static const union decode_item t16_table_1011[] = {
 	DECODE_SIMULATE	(0xffcf, 0xbf00, kprobe_simulate_nop),
 	/* Unassigned hints		1011 1111 xxxx 0000 */
 	DECODE_REJECT	(0xff0f, 0xbf00),
+	/* IT				1011 1111 xxxx xxxx */
+	DECODE_CUSTOM	(0xff00, 0xbf00, t16_decode_it),
 
 	DECODE_END
 };
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 31/51] ARM: kprobes: Reject 16-bit Thumb SVC and UNDEFINED instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (29 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 30/51] ARM: kprobes: Decode 16-bit Thumb IT instruction Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 32/51] ARM: kprobes: Decode 16-bit Thumb branch instructions Tixy
                   ` (20 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

SVC (SWI) instructions shouldn't occur in kernel code so we don't
need to be able to probe them.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index e496948..997fc6d 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -464,6 +464,14 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	/* LDM				1100 1xxx xxxx xxxx */
 	DECODE_EMULATE	(0xf000, 0xc000, t16_emulate_loregs_rwflags),
 
+	/*
+	 * Conditional branch, and Supervisor Call
+	 */
+
+	/* Permanently UNDEFINED	1101 1110 xxxx xxxx */
+	/* SVC				1101 1111 xxxx xxxx */
+	DECODE_REJECT	(0xfe00, 0xde00),
+
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 32/51] ARM: kprobes: Decode 16-bit Thumb branch instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (30 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 31/51] ARM: kprobes: Reject 16-bit Thumb SVC and UNDEFINED instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 33/51] ARM: kprobes: Reject 16-bit Thumb SETEND, CPS and BKPT instructions Tixy
                   ` (19 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

We previously changed the behaviour of probes so that conditional
instructions don't fire when the condition isn't met. For ARM branches,
and Thumb branches in IT blocks, this means they don't fire if the
branch isn't taken.

For consistency, we implement the same for Thumb conditional branch
instructions. This involves setting up insn_check_cc to point to the
relevant condition checking function. As the emulation routine is only
called when this condition passes, it doesn't need to check again and
can unconditionally update PC.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 997fc6d..d3133fd 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -141,6 +141,35 @@ t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 	return INSN_GOOD_NO_SLOT;
 }
 
+static void __kprobes
+t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	long offset = insn & 0x7f;
+	offset -= insn & 0x80; /* Apply sign bit */
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	int cc = (insn >> 8) & 0xf;
+	asi->insn_check_cc = kprobe_condition_checks[cc];
+	asi->insn_handler = t16_simulate_cond_branch;
+	return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t16_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	long offset = insn & 0x3ff;
+	offset -= insn & 0x400; /* Apply sign bit */
+	regs->ARM_pc = pc + (offset * 2);
+}
+
 static unsigned long __kprobes
 t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs)
 {
@@ -472,6 +501,15 @@ const union decode_item kprobe_decode_thumb16_table[] = {
 	/* SVC				1101 1111 xxxx xxxx */
 	DECODE_REJECT	(0xfe00, 0xde00),
 
+	/* Conditional branch		1101 xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xf000, 0xd000, t16_decode_cond_branch),
+
+	/*
+	 * Unconditional branch
+	 * B				1110 0xxx xxxx xxxx
+	 */
+	DECODE_SIMULATE	(0xf800, 0xe000, t16_simulate_branch),
+
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 33/51] ARM: kprobes: Reject 16-bit Thumb SETEND, CPS and BKPT instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (31 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 32/51] ARM: kprobes: Decode 16-bit Thumb branch instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 34/51] ARM: kprobes: Decode 32-bit Thumb hint instructions Tixy
                   ` (18 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

These are very rare and/or problematic to emulate so we will take the
easy option and disallow probing them (as does the existing ARM
implementation).

Rejecting these instructions doesn't actually require any entries in the
decoding table as it is the default case for instructions which aren't
found.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index d3133fd..554578b 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -373,6 +373,10 @@ static const union decode_item t16_table_1011[] = {
 	/* IT				1011 1111 xxxx xxxx */
 	DECODE_CUSTOM	(0xff00, 0xbf00, t16_decode_it),
 
+	/* SETEND			1011 0110 010x xxxx */
+	/* CPS				1011 0110 011x xxxx */
+	/* BKPT				1011 1110 xxxx xxxx */
+	/* And unallocated instructions...		    */
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 34/51] ARM: kprobes: Decode 32-bit Thumb hint instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (32 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 33/51] ARM: kprobes: Reject 16-bit Thumb SETEND, CPS and BKPT instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 35/51] ARM: kprobes: Add load_write_pc() Tixy
                   ` (17 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

For hints which may have observable effects, like SEV (send event), we
use kprobe_emulate_none which emulates the hint by executing the
original instruction.

For NOP we simulate the instruction using kprobe_simulate_nop, which
does nothing. As probes execute with interrupts disabled this is also
used for hints which may block for an indefinite time, like WFE (wait
for event).

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   28 +++++++++++++++++++++++++++-
 1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 554578b..27f83a3 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -37,6 +37,32 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
 	return (unsigned long)p->addr - 1 + 4;
 }
 
+static const union decode_item t32_table_1111_0xxx___1[] = {
+	/* Branches and miscellaneous control				*/
+
+	/* YIELD		1111 0011 1010 xxxx 10x0 x000 0000 0001 */
+	DECODE_OR	(0xfff0d7ff, 0xf3a08001),
+	/* SEV			1111 0011 1010 xxxx 10x0 x000 0000 0100 */
+	DECODE_EMULATE	(0xfff0d7ff, 0xf3a08004, kprobe_emulate_none),
+	/* NOP			1111 0011 1010 xxxx 10x0 x000 0000 0000 */
+	/* WFE			1111 0011 1010 xxxx 10x0 x000 0000 0010 */
+	/* WFI			1111 0011 1010 xxxx 10x0 x000 0000 0011 */
+	DECODE_SIMULATE	(0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
+
+	DECODE_END
+};
+
+const union decode_item kprobe_decode_thumb32_table[] = {
+
+	/*
+	 * Branches and miscellaneous control
+	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
+
+	DECODE_END
+};
+
 static void __kprobes
 t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs)
 {
@@ -551,5 +577,5 @@ thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
 	asi->insn_singlestep = thumb32_singlestep;
 	asi->insn_check_cc = thumb_check_cc;
-	return INSN_REJECTED;
+	return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true);
 }
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 35/51] ARM: kprobes: Add load_write_pc()
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (33 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 34/51] ARM: kprobes: Decode 32-bit Thumb hint instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 36/51] ARM: kprobes: Add common decoding function for LDM and STM Tixy
                   ` (16 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This writes a value to PC which was obtained as the result of a
LDR or LDM instruction. For ARMv5T and later this must perform
interworking.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |   24 ++++++++++++++++++++++++
 arch/arm/kernel/kprobes-common.c |   15 +++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 12627a3..5d6bf0d 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -109,6 +109,30 @@ static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
 	regs->ARM_pc = pcv;
 }
 
+
+#if __LINUX_ARM_ARCH__ >= 6
+
+/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */
+#define load_write_pc_interworks true
+#define test_load_write_pc_interworking()
+
+#else /* __LINUX_ARM_ARCH__ < 6 */
+
+/* We need run-time testing to determine if load_write_pc() should interwork. */
+extern bool load_write_pc_interworks;
+void __init test_load_write_pc_interworking(void);
+
+#endif
+
+static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
+{
+	if (load_write_pc_interworks)
+		bx_write_pc(pcv, regs);
+	else
+		regs->ARM_pc = pcv;
+}
+
+
 void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
 void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
 
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 84c0c74..41e8218 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -45,9 +45,24 @@ void __init find_str_pc_offset(void)
 #endif /* !find_str_pc_offset */
 
 
+#ifndef test_load_write_pc_interworking
+
+bool load_write_pc_interworks;
+
+void __init test_load_write_pc_interworking(void)
+{
+	int arch = cpu_architecture();
+	BUG_ON(arch == CPU_ARCH_UNKNOWN);
+	load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T;
+}
+
+#endif /* !test_load_write_pc_interworking */
+
+
 void __init arm_kprobe_decode_init(void)
 {
 	find_str_pc_offset();
+	test_load_write_pc_interworking();
 }
 
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 36/51] ARM: kprobes: Add common decoding function for LDM and STM
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (34 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 35/51] ARM: kprobes: Add load_write_pc() Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 37/51] ARM: kprobes: Optimise emulation of " Tixy
                   ` (15 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The encoding of these instructions is substantially the same for both
ARM and Thumb, so we can have common decoding and simulation functions.

This patch moves the simulation functions from kprobes-arm.c to
kprobes-common.c. It also adds a new simulation function
(simulate_ldm1_pc) for the case where we load into PC because this may
need to interwork.

The instruction decoding is done by a custom function
(kprobe_decode_ldmstm) rather than just relying on decoding table
entries because we will later be adding optimisation code.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes.h        |    3 ++
 arch/arm/kernel/kprobes-arm.c    |   58 ++++---------------------------
 arch/arm/kernel/kprobes-common.c |   70 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+), 51 deletions(-)

diff --git a/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h
index 5d6bf0d..c442852 100644
--- a/arch/arm/kernel/kprobes.h
+++ b/arch/arm/kernel/kprobes.h
@@ -136,6 +136,9 @@ static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs)
 void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs);
 void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs);
 
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi);
+
 /*
  * Test if load/store instructions writeback the address register.
  * if P (bit 24) == 0 or W (bit 21) == 1
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c
index a1143e8..c6f2c69 100644
--- a/arch/arm/kernel/kprobes-arm.c
+++ b/arch/arm/kernel/kprobes-arm.c
@@ -437,54 +437,6 @@ static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
 	regs->uregs[rd] = regs->ARM_cpsr & mask;
 }
 
-static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
-{
-	kprobe_opcode_t insn = p->opcode;
-	int rn = (insn >> 16) & 0xf;
-	int lbit = insn & (1 << 20);
-	int wbit = insn & (1 << 21);
-	int ubit = insn & (1 << 23);
-	int pbit = insn & (1 << 24);
-	long *addr = (long *)regs->uregs[rn];
-	int reg_bit_vector;
-	int reg_count;
-
-	reg_count = 0;
-	reg_bit_vector = insn & 0xffff;
-	while (reg_bit_vector) {
-		reg_bit_vector &= (reg_bit_vector - 1);
-		++reg_count;
-	}
-
-	if (!ubit)
-		addr -= reg_count;
-	addr += (!pbit == !ubit);
-
-	reg_bit_vector = insn & 0xffff;
-	while (reg_bit_vector) {
-		int reg = __ffs(reg_bit_vector);
-		reg_bit_vector &= (reg_bit_vector - 1);
-		if (lbit)
-			regs->uregs[reg] = *addr++;
-		else
-			*addr++ = regs->uregs[reg];
-	}
-
-	if (wbit) {
-		if (!ubit)
-			addr -= reg_count;
-		addr -= (!pbit == !ubit);
-		regs->uregs[rn] = (long)addr;
-	}
-}
-
-static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
-{
-	regs->ARM_pc = (long)p->addr + str_pc_offset;
-	simulate_ldm1stm1(p, regs);
-	regs->ARM_pc = (long)p->addr + 4;
-}
-
 static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
 {
 	regs->uregs[12] = regs->uregs[13];
@@ -1463,9 +1415,13 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
 	/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
 	/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
-	asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
-				simulate_stm1_pc : simulate_ldm1stm1;
-	return INSN_GOOD_NO_SLOT;
+
+	/*
+	 * Make the instruction unconditional because the new emulation
+	 * functions don't bother to setup the PSR context.
+	 */
+	insn = (insn | 0xe0000000) & ~0x10000000;
+	return kprobe_decode_ldmstm(insn, asi);
 }
 
 static enum kprobe_insn __kprobes
diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 41e8218..9ac1427 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -166,6 +166,76 @@ void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs)
 	p->ainsn.insn_fn();
 }
 
+static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rn = (insn >> 16) & 0xf;
+	int lbit = insn & (1 << 20);
+	int wbit = insn & (1 << 21);
+	int ubit = insn & (1 << 23);
+	int pbit = insn & (1 << 24);
+	long *addr = (long *)regs->uregs[rn];
+	int reg_bit_vector;
+	int reg_count;
+
+	reg_count = 0;
+	reg_bit_vector = insn & 0xffff;
+	while (reg_bit_vector) {
+		reg_bit_vector &= (reg_bit_vector - 1);
+		++reg_count;
+	}
+
+	if (!ubit)
+		addr -= reg_count;
+	addr += (!pbit == !ubit);
+
+	reg_bit_vector = insn & 0xffff;
+	while (reg_bit_vector) {
+		int reg = __ffs(reg_bit_vector);
+		reg_bit_vector &= (reg_bit_vector - 1);
+		if (lbit)
+			regs->uregs[reg] = *addr++;
+		else
+			*addr++ = regs->uregs[reg];
+	}
+
+	if (wbit) {
+		if (!ubit)
+			addr -= reg_count;
+		addr -= (!pbit == !ubit);
+		regs->uregs[rn] = (long)addr;
+	}
+}
+
+static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	regs->ARM_pc = (long)p->addr + str_pc_offset;
+	simulate_ldm1stm1(p, regs);
+	regs->ARM_pc = (long)p->addr + 4;
+}
+
+static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
+{
+	simulate_ldm1stm1(p, regs);
+	load_write_pc(regs->ARM_pc, regs);
+}
+
+enum kprobe_insn __kprobes
+kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	kprobe_insn_handler_t *handler = 0;
+	unsigned reglist = insn & 0xffff;
+	int is_ldm = insn & 0x100000;
+
+	if (reglist & 0x8000)
+		handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
+	else
+		handler = simulate_ldm1stm1;
+	asi->insn_handler = handler;
+	return INSN_GOOD_NO_SLOT;
+}
+
+
 /*
  * Prepare an instruction slot to receive an instruction for emulating.
  * This is done by placing a subroutine return after the location where the
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 37/51] ARM: kprobes: Optimise emulation of LDM and STM
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (35 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 36/51] ARM: kprobes: Add common decoding function for LDM and STM Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-12  0:45   ` Nicolas Pitre
  2011-07-09 10:57 ` [PATCH 38/51] ARM: kprobes: Decode 32-bit Thumb load/store multiple instructions Tixy
                   ` (14 subsequent siblings)
  51 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

This patch improves the performance of LDM and STM instruction
emulation. This is desirable because.

- jprobes and kretprobes probe the first instruction in a function and,
  when the frame pointer is omitted, this instruction is often a STM
  used to push registers onto the stack.

- The STM and LDM instructions are common in the body and tail of
  functions.

- At the same time as being a common instruction form, they also have
  one of the slowest and most complicated simulation routines.

The approach taken to optimisation is to use simulation rather than
emulation, that is, a modified form of the instruction is run with
an appropriate register context.

Benchmarking on an OMAP3530 shows the optimised emulation is between 2
and 3 times faster than the simulation routines. On a Kirkwood based
device the relative performance was very significantly better than this.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-common.c |   68 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c
index 9ac1427..765c682 100644
--- a/arch/arm/kernel/kprobes-common.c
+++ b/arch/arm/kernel/kprobes-common.c
@@ -220,13 +220,81 @@ static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs)
 	load_write_pc(regs->ARM_pc, regs);
 }
 
+static void __kprobes
+emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	register void *rregs asm("r1") = regs;
+	register void *rfn asm("lr") = p->ainsn.insn_fn;
+
+	__asm__ __volatile__ (
+		"stmdb	sp!, {%[regs], r11}	\n\t"
+		"ldmia	%[regs], {r0-r12}	\n\t"
+#if __LINUX_ARM_ARCH__ >= 6
+		"blx	%[fn]			\n\t"
+#else
+		"str	%[fn], [sp, #-4]!	\n\t"
+		"adr	lr, 1f			\n\t"
+		"ldr	pc, [sp], #4		\n\t"
+		"1:				\n\t"
+#endif
+		"ldr	lr, [sp], #4		\n\t" /* lr = regs */
+		"stmia	lr, {r0-r12}		\n\t"
+		"ldr	r11, [sp], #4		\n\t"
+		: [regs] "=r" (rregs), [fn] "=r" (rfn)
+		: "0" (rregs), "1" (rfn)
+		: "r0", "r2", "r3", "r4", "r5", "r6", "r7",
+		  "r8", "r9", "r10", "r12", "memory", "cc"
+		);
+}
+
+static void __kprobes
+emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
+}
+
+static void __kprobes
+emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
+{
+	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
+	load_write_pc(regs->ARM_pc, regs);
+}
+
 enum kprobe_insn __kprobes
 kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
 	kprobe_insn_handler_t *handler = 0;
 	unsigned reglist = insn & 0xffff;
 	int is_ldm = insn & 0x100000;
+	int rn = (insn >> 16) & 0xf;
+
+	if (rn <= 12 && (reglist & 0xe000) == 0) {
+		/* Instruction only uses registers in the range R0..R12 */
+		handler = emulate_generic_r0_12_noflags;
+
+	} else if (rn >= 2 && (reglist & 0x8003) == 0) {
+		/* Instruction only uses registers in the range R2..R14 */
+		rn -= 2;
+		reglist >>= 2;
+		handler = emulate_generic_r2_14_noflags;
+
+	} else if (rn >= 3 && (reglist & 0x0007) == 0) {
+		/* Instruction only uses registers in the range R3..R15 */
+		if (is_ldm && (reglist & 0x8000)) {
+			rn -= 3;
+			reglist >>= 3;
+			handler = emulate_ldm_r3_15;
+		}
+	}
+
+	if (handler) {
+		/* We can emulate the instruction in (possibly) modified form */
+		asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
+		asi->insn_handler = handler;
+		return INSN_GOOD;
+	}
 
+	/* Fallback to slower simulation... */
 	if (reglist & 0x8000)
 		handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc;
 	else
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 38/51] ARM: kprobes: Decode 32-bit Thumb load/store multiple instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (36 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 37/51] ARM: kprobes: Optimise emulation of " Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 39/51] ARM: kprobes: Decode 32-bit Thumb load/store dual and load/store exclusive instructions Tixy
                   ` (13 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   48 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 27f83a3..d25e5cb 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -37,6 +37,48 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
 	return (unsigned long)p->addr - 1 + 4;
 }
 
+static enum kprobe_insn __kprobes
+t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
+
+	/* Fixup modified instruction to have halfwords in correct order...*/
+	insn = asi->insn[0];
+	((u16 *)asi->insn)[0] = insn >> 16;
+	((u16 *)asi->insn)[1] = insn & 0xffff;
+
+	return ret;
+}
+
+static const union decode_item t32_table_1110_100x_x0xx[] = {
+	/* Load/store multiple instructions */
+
+	/* Rn is PC		1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe4f0000, 0xe80f0000),
+
+	/* SRS			1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE			1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffc00000, 0xe8000000),
+	/* SRS			1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE			1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffc00000, 0xe9800000),
+
+	/* STM Rn, {...pc}	1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe508000, 0xe8008000),
+	/* LDM Rn, {...lr,pc}	1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe50c000, 0xe810c000),
+	/* LDM/STM Rn, {...sp}	1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe402000, 0xe8002000),
+
+	/* STMIA		1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDMIA		1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */
+	/* STMDB		1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDMDB		1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xfe400000, 0xe8000000, t32_decode_ldmstm),
+
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* Branches and miscellaneous control				*/
 
@@ -55,6 +97,12 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
 const union decode_item kprobe_decode_thumb32_table[] = {
 
 	/*
+	 * Load/store multiple instructions
+	 *			1110 100x x0xx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
+
+	/*
 	 * Branches and miscellaneous control
 	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 39/51] ARM: kprobes: Decode 32-bit Thumb load/store dual and load/store exclusive instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (37 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 38/51] ARM: kprobes: Decode 32-bit Thumb load/store multiple instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 40/51] ARM: kprobes: Decode 32-bit Thumb table branch instructions Tixy
                   ` (12 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

We reject probing of load/store exclusive instructions because any
emulation routine could never succeed in gaining exclusive access as the
exception framework clears the exclusivity monitor when a probes
breakpoint is hit.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   56 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index d25e5cb..299dc3a 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -50,6 +50,33 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 	return ret;
 }
 
+static void __kprobes
+t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p) & ~3;
+	int rt1 = (insn >> 12) & 0xf;
+	int rt2 = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+
+	register unsigned long rt1v asm("r0") = regs->uregs[rt1];
+	register unsigned long rt2v asm("r1") = regs->uregs[rt2];
+	register unsigned long rnv asm("r2") = (rn == 15) ? pc
+							  : regs->uregs[rn];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rt1v), "=r" (rt2v), "=r" (rnv)
+		: "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	if (rn != 15)
+		regs->uregs[rn] = rnv; /* Writeback base register */
+	regs->uregs[rt1] = rt1v;
+	regs->uregs[rt2] = rt2v;
+}
+
 static const union decode_item t32_table_1110_100x_x0xx[] = {
 	/* Load/store multiple instructions */
 
@@ -79,6 +106,29 @@ static const union decode_item t32_table_1110_100x_x0xx[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1110_100x_x1xx[] = {
+	/* Load/store dual, load/store exclusive, table branch */
+
+	/* STRD (immediate)	1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRD (immediate)	1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_OR	(0xff600000, 0xe8600000),
+	/* STRD (immediate)	1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRD (immediate)	1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
+						 REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
+
+	/* STREX		1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
+	/* LDREX		1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
+	/* STREXB		1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
+	/* STREXH		1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */
+	/* STREXD		1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */
+	/* LDREXB		1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */
+	/* LDREXH		1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */
+	/* LDREXD		1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */
+	/* And unallocated instructions...				*/
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* Branches and miscellaneous control				*/
 
@@ -103,6 +153,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx),
 
 	/*
+	 * Load/store dual, load/store exclusive, table branch
+	 *			1110 100x x1xx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
+
+	/*
 	 * Branches and miscellaneous control
 	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 40/51] ARM: kprobes: Decode 32-bit Thumb table branch instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (38 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 39/51] ARM: kprobes: Decode 32-bit Thumb load/store dual and load/store exclusive instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 41/51] ARM: kprobes: Decode 32-bit Thumb data-processing (shifted register) instructions Tixy
                   ` (11 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 299dc3a..dfaea25 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -37,6 +37,26 @@ static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p)
 	return (unsigned long)p->addr - 1 + 4;
 }
 
+static void __kprobes
+t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn];
+	unsigned long rmv = regs->uregs[rm];
+	unsigned int halfwords;
+
+	if (insn & 0x10)
+		halfwords = ((u16 *)rnv)[rmv];
+	else
+		halfwords = ((u8 *)rnv)[rmv];
+
+	regs->ARM_pc = pc + 2 * halfwords;
+}
+
 static enum kprobe_insn __kprobes
 t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
@@ -117,6 +137,11 @@ static const union decode_item t32_table_1110_100x_x1xx[] = {
 	DECODE_EMULATEX	(0xff400000, 0xe9400000, t32_emulate_ldrdstrd,
 						 REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)),
 
+	/* TBB			1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */
+	/* TBH			1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch,
+						 REGS(NOSP, 0, 0, 0, NOSPPC)),
+
 	/* STREX		1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */
 	/* LDREX		1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */
 	/* STREXB		1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 41/51] ARM: kprobes: Decode 32-bit Thumb data-processing (shifted register) instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (39 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 40/51] ARM: kprobes: Decode 32-bit Thumb table branch instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 42/51] ARM: kprobes: Decode 32-bit Thumb data-processing (modified immediate) instructions Tixy
                   ` (10 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   93 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index dfaea25..eac945c 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -97,6 +97,33 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
 	regs->uregs[rt2] = rt2v;
 }
 
+static void __kprobes
+t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+	unsigned long cpsr = regs->ARM_cpsr;
+
+	__asm__ __volatile__ (
+		"msr	cpsr_fs, %[cpsr]	\n\t"
+		"blx    %[fn]			\n\t"
+		"mrs	%[cpsr], cpsr		\n\t"
+		: "=r" (rdv), [cpsr] "=r" (cpsr)
+		: "0" (rdv), "r" (rnv), "r" (rmv),
+		  "1" (cpsr), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
+}
+
 static const union decode_item t32_table_1110_100x_x0xx[] = {
 	/* Load/store multiple instructions */
 
@@ -154,6 +181,66 @@ static const union decode_item t32_table_1110_100x_x1xx[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1110_101x[] = {
+	/* Data-processing (shifted register)				*/
+
+	/* TST			1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */
+	/* TEQ			1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, 0, 0, NOSPPC)),
+
+	/* CMN			1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_OR	(0xfff00f00, 0xeb100f00),
+	/* CMP			1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOPC, 0, 0, 0, NOSPPC)),
+
+	/* MOV			1110 1010 010x 1111 xxxx xxxx xxxx xxxx */
+	/* MVN			1110 1010 011x 1111 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+	/* ???			1110 1010 101x xxxx xxxx xxxx xxxx xxxx */
+	/* ???			1110 1010 111x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffa00000, 0xeaa00000),
+	/* ???			1110 1011 001x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xeb200000),
+	/* ???			1110 1011 100x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xeb800000),
+	/* ???			1110 1011 111x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xffe00000, 0xebe00000),
+
+	/* ADD/SUB SP, SP, Rm, LSL #0..3				*/
+	/*			1110 1011 x0xx 1101 x000 1101 xx00 xxxx */
+	DECODE_EMULATEX	(0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, SP, 0, NOSPPC)),
+
+	/* ADD/SUB SP, SP, Rm, shift					*/
+	/*			1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */
+	DECODE_REJECT	(0xff4f0f00, 0xeb0d0d00),
+
+	/* ADD/SUB Rd, SP, Rm, shift					*/
+	/*			1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, NOPC, 0, NOSPPC)),
+
+	/* AND			1110 1010 000x xxxx xxxx xxxx xxxx xxxx */
+	/* BIC			1110 1010 001x xxxx xxxx xxxx xxxx xxxx */
+	/* ORR			1110 1010 010x xxxx xxxx xxxx xxxx xxxx */
+	/* ORN			1110 1010 011x xxxx xxxx xxxx xxxx xxxx */
+	/* EOR			1110 1010 100x xxxx xxxx xxxx xxxx xxxx */
+	/* PKH			1110 1010 110x xxxx xxxx xxxx xxxx xxxx */
+	/* ADD			1110 1011 000x xxxx xxxx xxxx xxxx xxxx */
+	/* ADC			1110 1011 010x xxxx xxxx xxxx xxxx xxxx */
+	/* SBC			1110 1011 011x xxxx xxxx xxxx xxxx xxxx */
+	/* SUB			1110 1011 101x xxxx xxxx xxxx xxxx xxxx */
+	/* RSB			1110 1011 110x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* Branches and miscellaneous control				*/
 
@@ -184,6 +271,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx),
 
 	/*
+	 * Data-processing (shifted register)
+	 *			1110 101x xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe000000, 0xea000000, t32_table_1110_101x),
+
+	/*
 	 * Branches and miscellaneous control
 	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 42/51] ARM: kprobes: Decode 32-bit Thumb data-processing (modified immediate) instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (40 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 41/51] ARM: kprobes: Decode 32-bit Thumb data-processing (shifted register) instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 43/51] ARM: kprobes: Decode 32-bit Thumb data-processing (plain binary " Tixy
                   ` (9 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   58 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index eac945c..cf83448 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -241,6 +241,58 @@ static const union decode_item t32_table_1110_101x[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_0x0x___0[] = {
+	/* Data-processing (modified immediate)				*/
+
+	/* TST			1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */
+	/* TEQ			1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, 0, 0, 0)),
+
+	/* CMN			1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_OR	(0xfbf08f00, 0xf1100f00),
+	/* CMP			1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOPC, 0, 0, 0, 0)),
+
+	/* MOV			1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */
+	/* MVN			1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* ???			1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf0a00000),
+	/* ???			1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */
+	/* ???			1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbc08000, 0xf0c00000),
+	/* ???			1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1200000),
+	/* ???			1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1800000),
+	/* ???			1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfbe08000, 0xf1e00000),
+
+	/* ADD Rd, SP, #imm	1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */
+	/* SUB Rd, SP, #imm	1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(SP, 0, NOPC, 0, 0)),
+
+	/* AND			1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */
+	/* BIC			1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */
+	/* ORR			1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */
+	/* ORN			1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */
+	/* EOR			1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */
+	/* ADD			1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */
+	/* ADC			1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */
+	/* SBC			1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */
+	/* SUB			1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */
+	/* RSB			1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* Branches and miscellaneous control				*/
 
@@ -277,6 +329,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe000000, 0xea000000, t32_table_1110_101x),
 
 	/*
+	 * Data-processing (modified immediate)
+	 *			1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
+
+	/*
 	 * Branches and miscellaneous control
 	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 43/51] ARM: kprobes: Decode 32-bit Thumb data-processing (plain binary immediate) instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (41 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 42/51] ARM: kprobes: Decode 32-bit Thumb data-processing (modified immediate) instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 44/51] ARM: kprobes: Decode 32-bit miscellaneous control instructions Tixy
                   ` (8 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   95 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index cf83448..1fbeba8 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -124,6 +124,46 @@ t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
 }
 
+static void __kprobes
+t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+	int rd = (insn >> 8) & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = pc & ~3;
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdv)
+		: "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+}
+
+static void __kprobes
+t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+
+	register unsigned long rdv asm("r1") = regs->uregs[rd];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdv)
+		: "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rd] = rdv;
+}
+
 static const union decode_item t32_table_1110_100x_x0xx[] = {
 	/* Load/store multiple instructions */
 
@@ -293,6 +333,55 @@ static const union decode_item t32_table_1111_0x0x___0[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_0x1x___0[] = {
+	/* Data-processing (plain binary immediate)			*/
+
+	/* ADDW Rd, PC, #imm	1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */
+	DECODE_OR	(0xfbff8000, 0xf20f0000),
+	/* SUBW	Rd, PC, #imm	1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags,
+						 REGS(PC, 0, NOSPPC, 0, 0)),
+
+	/* ADDW SP, SP, #imm	1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */
+	DECODE_OR	(0xfbff8f00, 0xf20d0d00),
+	/* SUBW	SP, SP, #imm	1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags,
+						 REGS(SP, 0, SP, 0, 0)),
+
+	/* ADDW			1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_OR	(0xfbf08000, 0xf2000000),
+	/* SUBW			1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOPCX, 0, NOSPPC, 0, 0)),
+
+	/* MOVW			1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */
+	/* MOVT			1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* SSAT16		1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */
+	/* SSAT			1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */
+	/* USAT16		1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */
+	/* USAT			1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	/* SFBX			1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */
+	/* UFBX			1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, 0)),
+
+	/* BFC			1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/* BFI			1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPCX, 0, NOSPPC, 0, 0)),
+
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* Branches and miscellaneous control				*/
 
@@ -335,6 +424,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfa008000, 0xf0000000, t32_table_1111_0x0x___0),
 
 	/*
+	 * Data-processing (plain binary immediate)
+	 *			1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfa008000, 0xf2000000, t32_table_1111_0x1x___0),
+
+	/*
 	 * Branches and miscellaneous control
 	 *			1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 44/51] ARM: kprobes: Decode 32-bit miscellaneous control instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (42 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 43/51] ARM: kprobes: Decode 32-bit Thumb data-processing (plain binary " Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 45/51] ARM: kprobes: Decode 32-bit Thumb branch instructions Tixy
                   ` (7 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 1fbeba8..c07c247 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -57,6 +57,15 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
 	regs->ARM_pc = pc + 2 * halfwords;
 }
 
+static void __kprobes
+t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 8) & 0xf;
+	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+	regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
 static enum kprobe_insn __kprobes
 t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
@@ -394,6 +403,28 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
 	/* WFI			1111 0011 1010 xxxx 10x0 x000 0000 0011 */
 	DECODE_SIMULATE	(0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop),
 
+	/* MRS Rd, CPSR		1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */
+	DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs,
+						 REGS(0, 0, NOSPPC, 0, 0)),
+
+	/*
+	 * Unsupported instructions
+	 *			1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx
+	 *
+	 * MSR			1111 0011 100x xxxx 10x0 xxxx xxxx xxxx
+	 * DBG hint		1111 0011 1010 xxxx 10x0 x000 1111 xxxx
+	 * Unallocated hints	1111 0011 1010 xxxx 10x0 x000 xxxx xxxx
+	 * CPS			1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx
+	 * CLREX/DSB/DMB/ISB	1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx
+	 * BXJ			1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx
+	 * SUBS PC,LR,#<imm8>	1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx
+	 * MRS Rd, SPSR		1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx
+	 * SMC			1111 0111 1111 xxxx 1000 xxxx xxxx xxxx
+	 * UNDEFINED		1111 0111 1111 xxxx 1010 xxxx xxxx xxxx
+	 * ???			1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xfb80d000, 0xf3808000),
+
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 45/51] ARM: kprobes: Decode 32-bit Thumb branch instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (43 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 44/51] ARM: kprobes: Decode 32-bit miscellaneous control instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 46/51] ARM: kprobes: Reject 32-bit Thumb coprocessor and SIMD instructions Tixy
                   ` (6 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   65 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index c07c247..1677234 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -49,9 +49,9 @@ t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs)
 	unsigned long rmv = regs->uregs[rm];
 	unsigned int halfwords;
 
-	if (insn & 0x10)
+	if (insn & 0x10) /* TBH */
 		halfwords = ((u16 *)rnv)[rmv];
-	else
+	else /* TBB */
 		halfwords = ((u8 *)rnv)[rmv];
 
 	regs->ARM_pc = pc + 2 * halfwords;
@@ -66,6 +66,58 @@ t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs)
 	regs->uregs[rd] = regs->ARM_cpsr & mask;
 }
 
+static void __kprobes
+t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+
+	long offset = insn & 0x7ff;		/* imm11 */
+	offset += (insn & 0x003f0000) >> 5;	/* imm6 */
+	offset += (insn & 0x00002000) << 4;	/* J1 */
+	offset += (insn & 0x00000800) << 7;	/* J2 */
+	offset -= (insn & 0x04000000) >> 7;	/* Apply sign bit */
+
+	regs->ARM_pc = pc + (offset * 2);
+}
+
+static enum kprobe_insn __kprobes
+t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	int cc = (insn >> 22) & 0xf;
+	asi->insn_check_cc = kprobe_condition_checks[cc];
+	asi->insn_handler = t32_simulate_cond_branch;
+	return INSN_GOOD_NO_SLOT;
+}
+
+static void __kprobes
+t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long pc = thumb_probe_pc(p);
+
+	long offset = insn & 0x7ff;		/* imm11 */
+	offset += (insn & 0x03ff0000) >> 5;	/* imm10 */
+	offset += (insn & 0x00002000) << 9;	/* J1 */
+	offset += (insn & 0x00000800) << 10;	/* J2 */
+	if (insn & 0x04000000)
+		offset -= 0x00800000; /* Apply sign bit */
+	else
+		offset ^= 0x00600000; /* Invert J1 and J2 */
+
+	if (insn & (1 << 14)) {
+		/* BL or BLX */
+		regs->ARM_lr = (unsigned long)p->addr + 4;
+		if (!(insn & (1 << 12))) {
+			/* BLX so switch to ARM mode */
+			regs->ARM_cpsr &= ~PSR_T_BIT;
+			pc &= ~3;
+		}
+	}
+
+	regs->ARM_pc = pc + (offset * 2);
+}
+
 static enum kprobe_insn __kprobes
 t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
@@ -425,6 +477,15 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
 	 */
 	DECODE_REJECT	(0xfb80d000, 0xf3808000),
 
+	/* Bcc			1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */
+	DECODE_CUSTOM	(0xf800d000, 0xf0008000, t32_decode_cond_branch),
+
+	/* BLX			1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */
+	DECODE_OR	(0xf800d001, 0xf000c000),
+	/* B			1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */
+	/* BL			1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xf8009000, 0xf0009000, t32_simulate_branch),
+
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 46/51] ARM: kprobes: Reject 32-bit Thumb coprocessor and SIMD instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (44 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 45/51] ARM: kprobes: Decode 32-bit Thumb branch instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 47/51] ARM: kprobes: Decode 32-bit Thumb memory hint instructions Tixy
                   ` (5 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

The kernel doesn't currently support VFP or Neon code, and probing of
code with CP15 operations is fraught with bad consequences. So we will
just reject probing these instructions.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 1677234..6cc51b4 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -510,6 +510,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe000000, 0xea000000, t32_table_1110_101x),
 
 	/*
+	 * Coprocessor instructions
+	 *			1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xfc000000, 0xec000000),
+
+	/*
 	 * Data-processing (modified immediate)
 	 *			1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx
 	 */
@@ -527,6 +533,16 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	 */
 	DECODE_TABLE	(0xf8008000, 0xf0008000, t32_table_1111_0xxx___1),
 
+	/*
+	 * Advanced SIMD element or structure load/store instructions
+	 *			1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_REJECT	(0xff100000, 0xf9000000),
+
+	/*
+	 * Coprocessor instructions
+	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
+	 */
 	DECODE_END
 };
 
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 47/51] ARM: kprobes: Decode 32-bit Thumb memory hint instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (45 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 46/51] ARM: kprobes: Reject 32-bit Thumb coprocessor and SIMD instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 48/51] ARM: kprobes: Decode 32-bit Thumb load/store single data item instructions Tixy
                   ` (4 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

We'll treat the preload instructions as nops as they are just
performance hints.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 6cc51b4..bf1113c 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -489,6 +489,33 @@ static const union decode_item t32_table_1111_0xxx___1[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
+	/* Memory hints							*/
+
+	/* PLD (literal)	1111 1000 x001 1111 1111 xxxx xxxx xxxx */
+	/* PLI (literal)	1111 1001 x001 1111 1111 xxxx xxxx xxxx */
+	DECODE_SIMULATE	(0xfe7ff000, 0xf81ff000, kprobe_simulate_nop),
+
+	/* PLD{W} (immediate)	1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_OR	(0xffd0f000, 0xf890f000),
+	/* PLD{W} (immediate)	1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */
+	DECODE_OR	(0xffd0ff00, 0xf810fc00),
+	/* PLI (immediate)	1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_OR	(0xfff0f000, 0xf990f000),
+	/* PLI (immediate)	1111 1001 0001 xxxx 1111 1100 xxxx xxxx */
+	DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop,
+						 REGS(NOPCX, 0, 0, 0, 0)),
+
+	/* PLD{W} (register)	1111 1000 00x1 xxxx 1111 0000 00xx xxxx */
+	DECODE_OR	(0xffd0ffc0, 0xf810f000),
+	/* PLI (register)	1111 1001 0001 xxxx 1111 0000 00xx xxxx */
+	DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop,
+						 REGS(NOPCX, 0, 0, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
 const union decode_item kprobe_decode_thumb32_table[] = {
 
 	/*
@@ -540,6 +567,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_REJECT	(0xff100000, 0xf9000000),
 
 	/*
+	 * Memory hints
+	 *			1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
+
+	/*
 	 * Coprocessor instructions
 	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 48/51] ARM: kprobes: Decode 32-bit Thumb load/store single data item instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (46 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 47/51] ARM: kprobes: Decode 32-bit Thumb memory hint instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 49/51] ARM: kprobes: Decode 32-bit Thumb data-processing (register) instructions Tixy
                   ` (3 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

We will reject probing of unprivileged load and store instructions.
These rarely occur and writing test cases for them is difficult.

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |  153 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 153 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index bf1113c..9be8bea 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -118,6 +118,44 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
 	regs->ARM_pc = pc + (offset * 2);
 }
 
+static void __kprobes
+t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	unsigned long addr = thumb_probe_pc(p) & ~3;
+	int rt = (insn >> 12) & 0xf;
+	unsigned long rtv;
+
+	long offset = insn & 0xfff;
+	if (insn & 0x00800000)
+		addr += offset;
+	else
+		addr -= offset;
+
+	if (insn & 0x00400000) {
+		/* LDR */
+		rtv = *(unsigned long *)addr;
+		if (rt == 15) {
+			bx_write_pc(rtv, regs);
+			return;
+		}
+	} else if (insn & 0x00200000) {
+		/* LDRH */
+		if (insn & 0x01000000)
+			rtv = *(s16 *)addr;
+		else
+			rtv = *(u16 *)addr;
+	} else {
+		/* LDRB */
+		if (insn & 0x01000000)
+			rtv = *(s8 *)addr;
+		else
+			rtv = *(u8 *)addr;
+	}
+
+	regs->uregs[rt] = rtv;
+}
+
 static enum kprobe_insn __kprobes
 t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
@@ -159,6 +197,32 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
 }
 
 static void __kprobes
+t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rt = (insn >> 12) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rtv asm("r0") = regs->uregs[rt];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rtv), "=r" (rnv)
+		: "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rn] = rnv; /* Writeback base register */
+	if (rt == 15) /* Can't be true for a STR as they aren't allowed */
+		bx_write_pc(rtv, regs);
+	else
+		regs->uregs[rt] = rtv;
+}
+
+static void __kprobes
 t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
 {
 	kprobe_opcode_t insn = p->opcode;
@@ -516,6 +580,87 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_100x[] = {
+	/* Store/Load single data item					*/
+
+	/* ???			1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfe600000, 0xf8600000),
+
+	/* ???			1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xfff00000, 0xf9500000),
+
+	/* ???			1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
+	DECODE_REJECT	(0xfe800d00, 0xf8000800),
+
+	/* STRBT		1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
+	/* STRHT		1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
+	/* STRT			1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRBT		1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRSBT		1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRHT		1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRSHT		1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
+	/* LDRT			1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
+	DECODE_REJECT	(0xfe800f00, 0xf8000e00),
+
+	/* STR{,B,H} Rn,[PC...]	1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
+	DECODE_REJECT	(0xff1f0000, 0xf80f0000),
+
+	/* STR{,B,H} PC,[Rn...]	1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
+	DECODE_REJECT	(0xff10f000, 0xf800f000),
+
+	/* LDR (literal)	1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
+	DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
+						 REGS(PC, ANY, 0, 0, 0)),
+
+	/* STR (immediate)	1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDR (immediate)	1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
+	DECODE_OR	(0xffe00800, 0xf8400800),
+	/* STR (immediate)	1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
+	/* LDR (immediate)	1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
+						 REGS(NOPCX, ANY, 0, 0, 0)),
+
+	/* STR (register)	1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
+	/* LDR (register)	1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
+	DECODE_EMULATEX	(0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
+						 REGS(NOPCX, ANY, 0, 0, NOSPPC)),
+
+	/* LDRB (literal)	1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
+	/* LDRSB (literal)	1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
+	/* LDRH (literal)	1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
+	/* LDRSH (literal)	1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
+						 REGS(PC, NOSPPCX, 0, 0, 0)),
+
+	/* STRB (immediate)	1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
+	/* STRH (immediate)	1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRB (immediate)	1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRSB (immediate)	1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRH (immediate)	1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
+	/* LDRSH (immediate)	1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
+	DECODE_OR	(0xfec00800, 0xf8000800),
+	/* STRB (immediate)	1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
+	/* STRH (immediate)	1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRB (immediate)	1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRSB (immediate)	1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRH (immediate)	1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
+	/* LDRSH (immediate)	1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
+	DECODE_EMULATEX	(0xfec00000, 0xf8800000, t32_emulate_ldrstr,
+						 REGS(NOPCX, NOSPPCX, 0, 0, 0)),
+
+	/* STRB (register)	1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
+	/* STRH (register)	1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
+	/* LDRB (register)	1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
+	/* LDRSB (register)	1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
+	/* LDRH (register)	1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
+	/* LDRSH (register)	1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
+	DECODE_EMULATEX	(0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
+						 REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
 const union decode_item kprobe_decode_thumb32_table[] = {
 
 	/*
@@ -573,6 +718,14 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
 
 	/*
+	 * Store single data item
+	 *			1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
+	 * Load single data items
+	 *			1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xfe000000, 0xf8000000, t32_table_1111_100x),
+
+	/*
 	 * Coprocessor instructions
 	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 49/51] ARM: kprobes: Decode 32-bit Thumb data-processing (register) instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (47 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 48/51] ARM: kprobes: Decode 32-bit Thumb load/store single data item instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 50/51] ARM: kprobes: Decode 32-bit Thumb long multiply and divide instructions Tixy
                   ` (2 subsequent siblings)
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |  108 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 9be8bea..7c32e5b 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -661,6 +661,108 @@ static const union decode_item t32_table_1111_100x[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_1010___1111[] = {
+	/* Data-processing (register)					*/
+
+	/* ???			1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */
+	DECODE_REJECT	(0xffe0f080, 0xfa60f080),
+
+	/* SXTH			1111 1010 0000 1111 1111 xxxx 1xxx xxxx */
+	/* UXTH			1111 1010 0001 1111 1111 xxxx 1xxx xxxx */
+	/* SXTB16		1111 1010 0010 1111 1111 xxxx 1xxx xxxx */
+	/* UXTB16		1111 1010 0011 1111 1111 xxxx 1xxx xxxx */
+	/* SXTB			1111 1010 0100 1111 1111 xxxx 1xxx xxxx */
+	/* UXTB			1111 1010 0101 1111 1111 xxxx 1xxx xxxx */
+	DECODE_EMULATEX	(0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(0, 0, NOSPPC, 0, NOSPPC)),
+
+
+	/* ???			1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */
+	DECODE_REJECT	(0xff80f0b0, 0xfa80f030),
+	/* ???			1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */
+	DECODE_REJECT	(0xffb0f080, 0xfab0f000),
+
+	/* SADD16		1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */
+	/* SASX			1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */
+	/* SSAX			1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */
+	/* SSUB16		1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */
+	/* SADD8		1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */
+	/* SSUB8		1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */
+
+	/* QADD16		1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */
+	/* QASX			1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */
+	/* QSAX			1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */
+	/* QSUB16		1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */
+	/* QADD8		1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */
+	/* QSUB8		1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */
+
+	/* SHADD16		1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */
+	/* SHASX		1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSAX		1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSUB16		1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */
+	/* SHADD8		1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */
+	/* SHSUB8		1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */
+
+	/* UADD16		1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */
+	/* UASX			1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */
+	/* USAX			1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */
+	/* USUB16		1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */
+	/* UADD8		1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */
+	/* USUB8		1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */
+
+	/* UQADD16		1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */
+	/* UQASX		1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSAX		1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSUB16		1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */
+	/* UQADD8		1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */
+	/* UQSUB8		1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */
+
+	/* UHADD16		1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */
+	/* UHASX		1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSAX		1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSUB16		1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */
+	/* UHADD8		1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */
+	/* UHSUB8		1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */
+	DECODE_OR	(0xff80f080, 0xfa80f000),
+
+	/* SXTAH		1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAH		1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */
+	/* SXTAB16		1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAB16		1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */
+	/* SXTAB		1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */
+	/* UXTAB		1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */
+	DECODE_OR	(0xff80f080, 0xfa00f080),
+
+	/* QADD			1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */
+	/* QDADD		1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */
+	/* QSUB			1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */
+	/* QDSUB		1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */
+	DECODE_OR	(0xfff0f0c0, 0xfa80f080),
+
+	/* SEL			1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+	DECODE_OR	(0xfff0f0f0, 0xfaa0f080),
+
+	/* LSL			1111 1010 000x xxxx 1111 xxxx 0000 xxxx */
+	/* LSR			1111 1010 001x xxxx 1111 xxxx 0000 xxxx */
+	/* ASR			1111 1010 010x xxxx 1111 xxxx 0000 xxxx */
+	/* ROR			1111 1010 011x xxxx 1111 xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	/* CLZ			1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */
+	DECODE_OR	(0xfff0f0f0, 0xfab0f080),
+
+	/* REV			1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */
+	/* REV16		1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */
+	/* RBIT			1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */
+	/* REVSH		1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */
+	DECODE_EMULATEX	(0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
 const union decode_item kprobe_decode_thumb32_table[] = {
 
 	/*
@@ -726,6 +828,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xfe000000, 0xf8000000, t32_table_1111_100x),
 
 	/*
+	 * Data-processing (register)
+	 *			1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
+
+	/*
 	 * Coprocessor instructions
 	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 50/51] ARM: kprobes: Decode 32-bit Thumb long multiply and divide instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (48 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 49/51] ARM: kprobes: Decode 32-bit Thumb data-processing (register) instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-09 10:57 ` [PATCH 51/51] ARM: kprobes: Decode 32-bit Thumb multiply and absolute difference instructions Tixy
  2011-07-12  1:02 ` ARM: kprobes: Add support for Thumb-2 Nicolas Pitre
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   55 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 7c32e5b..4ef12d1 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -289,6 +289,32 @@ t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs)
 	regs->uregs[rd] = rdv;
 }
 
+static void __kprobes
+t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rdlo = (insn >> 12) & 0xf;
+	int rdhi = (insn >> 8) & 0xf;
+	int rn = (insn >> 16) & 0xf;
+	int rm = insn & 0xf;
+
+	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
+	register unsigned long rdhiv asm("r1") = regs->uregs[rdhi];
+	register unsigned long rnv asm("r2") = regs->uregs[rn];
+	register unsigned long rmv asm("r3") = regs->uregs[rm];
+
+	__asm__ __volatile__ (
+		"blx    %[fn]"
+		: "=r" (rdlov), "=r" (rdhiv)
+		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
+		  [fn] "r" (p->ainsn.insn_fn)
+		: "lr", "memory", "cc"
+	);
+
+	regs->uregs[rdlo] = rdlov;
+	regs->uregs[rdhi] = rdhiv;
+}
+
 static const union decode_item t32_table_1110_100x_x0xx[] = {
 	/* Load/store multiple instructions */
 
@@ -763,6 +789,29 @@ static const union decode_item t32_table_1111_1010___1111[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_1011_1[] = {
+	/* Long multiply, long multiply accumulate, and divide		*/
+
+	/* UMAAL		1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */
+	DECODE_OR	(0xfff000f0, 0xfbe00060),
+	/* SMLALxy		1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */
+	DECODE_OR	(0xfff000c0, 0xfbc00080),
+	/* SMLALD{X}		1111 1011 1100 xxxx xxxx xxxx 110x xxxx */
+	/* SMLSLD{X}		1111 1011 1101 xxxx xxxx xxxx 110x xxxx */
+	DECODE_OR	(0xffe000e0, 0xfbc000c0),
+	/* SMULL		1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */
+	/* UMULL		1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */
+	/* SMLAL		1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */
+	/* UMLAL		1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags,
+						 REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)),
+
+	/* SDIV			1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */
+	/* UDIV			1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
 const union decode_item kprobe_decode_thumb32_table[] = {
 
 	/*
@@ -834,6 +883,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
 
 	/*
+	 * Long multiply, long multiply accumulate, and divide
+	 *			1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff800000, 0xfb800000, t32_table_1111_1011_1),
+
+	/*
 	 * Coprocessor instructions
 	 *			1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 51/51] ARM: kprobes: Decode 32-bit Thumb multiply and absolute difference instructions
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (49 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 50/51] ARM: kprobes: Decode 32-bit Thumb long multiply and divide instructions Tixy
@ 2011-07-09 10:57 ` Tixy
  2011-07-12  1:02 ` ARM: kprobes: Add support for Thumb-2 Nicolas Pitre
  51 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-09 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jon Medhurst <tixy@yxit.co.uk>

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
---
 arch/arm/kernel/kprobes-thumb.c |   49 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index 4ef12d1..902ca59 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -315,6 +315,10 @@ t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs)
 	regs->uregs[rdhi] = rdhiv;
 }
 
+/* These emulation encodings are functionally equivalent... */
+#define t32_emulate_rd8rn16rm0ra12_noflags \
+		t32_emulate_rdlo12rdhi8rn16rm0_noflags
+
 static const union decode_item t32_table_1110_100x_x0xx[] = {
 	/* Load/store multiple instructions */
 
@@ -789,6 +793,45 @@ static const union decode_item t32_table_1111_1010___1111[] = {
 	DECODE_END
 };
 
+static const union decode_item t32_table_1111_1011_0[] = {
+	/* Multiply, multiply accumulate, and absolute difference	*/
+
+	/* ???			1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff0f0f0, 0xfb00f010),
+	/* ???			1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff0f0f0, 0xfb70f010),
+
+	/* SMULxy		1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */
+	DECODE_OR	(0xfff0f0c0, 0xfb10f000),
+	/* MUL			1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */
+	/* SMUAD{X}		1111 1011 0010 xxxx 1111 xxxx 000x xxxx */
+	/* SMULWy		1111 1011 0011 xxxx 1111 xxxx 000x xxxx */
+	/* SMUSD{X}		1111 1011 0100 xxxx 1111 xxxx 000x xxxx */
+	/* SMMUL{R}		1111 1011 0101 xxxx 1111 xxxx 000x xxxx */
+	/* USAD8		1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags,
+						 REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)),
+
+	/* ???			1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */
+	DECODE_REJECT	(0xfff000f0, 0xfb700010),
+
+	/* SMLAxy		1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */
+	DECODE_OR	(0xfff000c0, 0xfb100000),
+	/* MLA			1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */
+	/* MLS			1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */
+	/* SMLAD{X}		1111 1011 0010 xxxx xxxx xxxx 000x xxxx */
+	/* SMLAWy		1111 1011 0011 xxxx xxxx xxxx 000x xxxx */
+	/* SMLSD{X}		1111 1011 0100 xxxx xxxx xxxx 000x xxxx */
+	/* SMMLA{R}		1111 1011 0101 xxxx xxxx xxxx 000x xxxx */
+	/* SMMLS{R}		1111 1011 0110 xxxx xxxx xxxx 000x xxxx */
+	/* USADA8		1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */
+	DECODE_EMULATEX	(0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags,
+						 REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)),
+
+	/* Other unallocated instructions...				*/
+	DECODE_END
+};
+
 static const union decode_item t32_table_1111_1011_1[] = {
 	/* Long multiply, long multiply accumulate, and divide		*/
 
@@ -883,6 +926,12 @@ const union decode_item kprobe_decode_thumb32_table[] = {
 	DECODE_TABLE	(0xff00f000, 0xfa00f000, t32_table_1111_1010___1111),
 
 	/*
+	 * Multiply, multiply accumulate, and absolute difference
+	 *			1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx
+	 */
+	DECODE_TABLE	(0xff800000, 0xfb000000, t32_table_1111_1011_0),
+
+	/*
 	 * Long multiply, long multiply accumulate, and divide
 	 *			1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx
 	 */
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels
  2011-07-09 10:56 ` [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels Tixy
@ 2011-07-11 11:01   ` Sergei Shtylyov
  2011-07-11 11:33     ` Tixy
  0 siblings, 1 reply; 65+ messages in thread
From: Sergei Shtylyov @ 2011-07-11 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hello.

On 09-07-2011 14:56, Tixy wrote:

> From: Jon Medhurst<tixy@yxit.co.uk>

> Signed-off-by: Jon Medhurst<tixy@yxit.co.uk>
> ---
>   arch/arm/Kconfig |    2 +-
>   1 files changed, 1 insertions(+), 1 deletions(-)

> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9adc278..b4177c5 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -10,7 +10,7 @@ config ARM
>   	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
>   	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
>   	select HAVE_ARCH_KGDB
> -	select HAVE_KPROBES if (!XIP_KERNEL&&  !THUMB2_KERNEL)
> +	select HAVE_KPROBES if (!XIP_KERNEL)

    Why not drop useless parens, while at it?

WBR, Sergei

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels
  2011-07-11 11:01   ` Sergei Shtylyov
@ 2011-07-11 11:33     ` Tixy
  2011-07-11 11:42       ` Russell King - ARM Linux
  0 siblings, 1 reply; 65+ messages in thread
From: Tixy @ 2011-07-11 11:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-11 at 15:01 +0400, Sergei Shtylyov wrote: 
> Hello.
> 
> On 09-07-2011 14:56, Tixy wrote:
> 
> > From: Jon Medhurst<tixy@yxit.co.uk>
> 
> > Signed-off-by: Jon Medhurst<tixy@yxit.co.uk>
> > ---
> >   arch/arm/Kconfig |    2 +-
> >   1 files changed, 1 insertions(+), 1 deletions(-)
> 
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 9adc278..b4177c5 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -10,7 +10,7 @@ config ARM
> >   	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
> >   	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
> >   	select HAVE_ARCH_KGDB
> > -	select HAVE_KPROBES if (!XIP_KERNEL&&  !THUMB2_KERNEL)
> > +	select HAVE_KPROBES if (!XIP_KERNEL)
> 
>     Why not drop useless parens, while at it?

Every other 'if' clause in that file has these parenthesis so I thought
I would kept it consistent.

-- 
Tixy 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels
  2011-07-11 11:33     ` Tixy
@ 2011-07-11 11:42       ` Russell King - ARM Linux
  2011-07-11 11:47         ` Tixy
  0 siblings, 1 reply; 65+ messages in thread
From: Russell King - ARM Linux @ 2011-07-11 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 11, 2011 at 12:33:41PM +0100, Tixy wrote:
> On Mon, 2011-07-11 at 15:01 +0400, Sergei Shtylyov wrote: 
> > Hello.
> > 
> > On 09-07-2011 14:56, Tixy wrote:
> > 
> > > From: Jon Medhurst<tixy@yxit.co.uk>
> > 
> > > Signed-off-by: Jon Medhurst<tixy@yxit.co.uk>
> > > ---
> > >   arch/arm/Kconfig |    2 +-
> > >   1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > > index 9adc278..b4177c5 100644
> > > --- a/arch/arm/Kconfig
> > > +++ b/arch/arm/Kconfig
> > > @@ -10,7 +10,7 @@ config ARM
> > >   	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
> > >   	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
> > >   	select HAVE_ARCH_KGDB
> > > -	select HAVE_KPROBES if (!XIP_KERNEL&&  !THUMB2_KERNEL)
> > > +	select HAVE_KPROBES if (!XIP_KERNEL)
> > 
> >     Why not drop useless parens, while at it?
> 
> Every other 'if' clause in that file has these parenthesis so I thought
> I would kept it consistent.

There's plenty of examples where this isn't the case, eg:

        default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
...
        default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
                ARCH_S5PV210 || ARCH_EXYNOS4
        default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
        default AT91_TIMER_HZ if ARCH_AT91
        default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
...
        depends on !ARCH_S5P64X0 && !ARCH_S5PC100
        depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
                CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE

We really need to stop useless additional parens for simple expressions.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels
  2011-07-11 11:42       ` Russell King - ARM Linux
@ 2011-07-11 11:47         ` Tixy
  0 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-11 11:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-11 at 12:42 +0100, Russell King - ARM Linux wrote:
> On Mon, Jul 11, 2011 at 12:33:41PM +0100, Tixy wrote:
> > On Mon, 2011-07-11 at 15:01 +0400, Sergei Shtylyov wrote: 
> > > Hello.
> > > 
> > > On 09-07-2011 14:56, Tixy wrote:
> > > 
> > > > From: Jon Medhurst<tixy@yxit.co.uk>
> > > 
> > > > Signed-off-by: Jon Medhurst<tixy@yxit.co.uk>
> > > > ---
> > > >   arch/arm/Kconfig |    2 +-
> > > >   1 files changed, 1 insertions(+), 1 deletions(-)
> > > 
> > > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > > > index 9adc278..b4177c5 100644
> > > > --- a/arch/arm/Kconfig
> > > > +++ b/arch/arm/Kconfig
> > > > @@ -10,7 +10,7 @@ config ARM
> > > >   	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
> > > >   	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
> > > >   	select HAVE_ARCH_KGDB
> > > > -	select HAVE_KPROBES if (!XIP_KERNEL&&  !THUMB2_KERNEL)
> > > > +	select HAVE_KPROBES if (!XIP_KERNEL)
> > > 
> > >     Why not drop useless parens, while at it?
> > 
> > Every other 'if' clause in that file has these parenthesis so I thought
> > I would kept it consistent.
> 
> There's plenty of examples where this isn't the case, 
[...]
> We really need to stop useless additional parens for simple expressions.

OK, fair enough.

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly
  2011-07-09 10:56 ` [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly Tixy
@ 2011-07-11 18:07   ` Nicolas Pitre
  0 siblings, 0 replies; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-11 18:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> From: Jon Medhurst <tixy@yxit.co.uk>
> 
> The implementation of svc_exit didn't take into account any stack hole
> created by svc_entry; as happens with the undef handler when kprobes are
> configured. The fix is to read the saved value of SP rather than trying
> to calculate it.
> 
> Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>

Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>


> ---
>  arch/arm/kernel/entry-header.S |   12 +++++-------
>  1 files changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
> index 051166c..83e29ad 100644
> --- a/arch/arm/kernel/entry-header.S
> +++ b/arch/arm/kernel/entry-header.S
> @@ -121,15 +121,13 @@
>  	.endm
>  #else	/* CONFIG_THUMB2_KERNEL */
>  	.macro	svc_exit, rpsr
> +	ldr	lr, [sp, #S_SP]			@ top of the stack
> +	ldrd	r0, r1, [sp, #S_LR]		@ calling lr and pc
>  	clrex					@ clear the exclusive monitor
> -	ldr	r0, [sp, #S_SP]			@ top of the stack
> -	ldr	r1, [sp, #S_PC]			@ return address
> -	tst	r0, #4				@ orig stack 8-byte aligned?
> -	stmdb	r0, {r1, \rpsr}			@ rfe context
> +	stmdb	lr!, {r0, r1, \rpsr}		@ calling lr and rfe context
>  	ldmia	sp, {r0 - r12}
> -	ldr	lr, [sp, #S_LR]
> -	addeq	sp, sp, #S_FRAME_SIZE - 8	@ aligned
> -	addne	sp, sp, #S_FRAME_SIZE - 4	@ not aligned
> +	mov	sp, lr
> +	ldr	lr, [sp], #4
>  	rfeia	sp!
>  	.endm
>  
> -- 
> 1.7.2.5
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler
  2011-07-09 10:56 ` [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler Tixy
@ 2011-07-11 18:14   ` Nicolas Pitre
  0 siblings, 0 replies; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-11 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> From: Jon Medhurst <tixy@yxit.co.uk>
> 
> This patch allows undef_hook's to be specified for 32-bit Thumb
> instructions and also to be used for thumb kernel-side code.
> 
> 32-bit Thumb instructions are specified in the form:
> 	((first_half << 16 ) | second_half)
> which matches the layout used by the ARM ARM.
> 
> ptrace was handling 32-bit Thumb instructions by hooking the first
> halfword and manually checking the second half. This method would be
> broken by this patch so it is migrated to make use of the new Thumb-2
> support.
> 
> Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>

Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>

> ---
>  arch/arm/include/asm/ptrace.h |    8 ++++++++
>  arch/arm/kernel/ptrace.c      |   28 +++-------------------------
>  arch/arm/kernel/traps.c       |   17 ++++++++++++++++-
>  3 files changed, 27 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
> index 312d108..d484871 100644
> --- a/arch/arm/include/asm/ptrace.h
> +++ b/arch/arm/include/asm/ptrace.h
> @@ -200,6 +200,14 @@ extern unsigned long profile_pc(struct pt_regs *regs);
>  #define PREDICATE_ALWAYS	0xe0000000
>  
>  /*
> + * True if instr is a 32-bit thumb instruction. This works if instr
> + * is the first or only half-word of a thumb instruction. It also works
> + * when instr holds all 32-bits of a wide thumb instruction if stored
> + * in the form (first_half<<16)|(second_half)
> + */
> +#define is_wide_instruction(instr)	((unsigned)(instr) >= 0xe800)
> +
> +/*
>   * kprobe-based event tracer support
>   */
>  #include <linux/stddef.h>
> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
> index 9726006..897ade0 100644
> --- a/arch/arm/kernel/ptrace.c
> +++ b/arch/arm/kernel/ptrace.c
> @@ -228,34 +228,12 @@ static struct undef_hook thumb_break_hook = {
>  	.fn		= break_trap,
>  };
>  
> -static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
> -{
> -	unsigned int instr2;
> -	void __user *pc;
> -
> -	/* Check the second half of the instruction.  */
> -	pc = (void __user *)(instruction_pointer(regs) + 2);
> -
> -	if (processor_mode(regs) == SVC_MODE) {
> -		instr2 = *(u16 *) pc;
> -	} else {
> -		get_user(instr2, (u16 __user *)pc);
> -	}
> -
> -	if (instr2 == 0xa000) {
> -		ptrace_break(current, regs);
> -		return 0;
> -	} else {
> -		return 1;
> -	}
> -}
> -
>  static struct undef_hook thumb2_break_hook = {
> -	.instr_mask	= 0xffff,
> -	.instr_val	= 0xf7f0,
> +	.instr_mask	= 0xffffffff,
> +	.instr_val	= 0xf7f0a000,
>  	.cpsr_mask	= PSR_T_BIT,
>  	.cpsr_val	= PSR_T_BIT,
> -	.fn		= thumb2_break_trap,
> +	.fn		= break_trap,
>  };
>  
>  static int __init ptrace_break_init(void)
> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
> index 6807cb1..2d3436e 100644
> --- a/arch/arm/kernel/traps.c
> +++ b/arch/arm/kernel/traps.c
> @@ -355,9 +355,24 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>  	pc = (void __user *)instruction_pointer(regs);
>  
>  	if (processor_mode(regs) == SVC_MODE) {
> -		instr = *(u32 *) pc;
> +#ifdef CONFIG_THUMB2_KERNEL
> +		if (thumb_mode(regs)) {
> +			instr = ((u16 *)pc)[0];
> +			if (is_wide_instruction(instr)) {
> +				instr <<= 16;
> +				instr |= ((u16 *)pc)[1];
> +			}
> +		} else
> +#endif
> +			instr = *(u32 *) pc;
>  	} else if (thumb_mode(regs)) {
>  		get_user(instr, (u16 __user *)pc);
> +		if (is_wide_instruction(instr)) {
> +			unsigned int instr2;
> +			get_user(instr2, (u16 __user *)pc+1);
> +			instr <<= 16;
> +			instr |= instr2;
> +		}
>  	} else {
>  		get_user(instr, (u32 __user *)pc);
>  	}
> -- 
> 1.7.2.5
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false
  2011-07-09 10:57 ` [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false Tixy
@ 2011-07-11 19:04   ` Nicolas Pitre
  0 siblings, 0 replies; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-11 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> From: Jon Medhurst <tixy@yxit.co.uk>
> 
> This patch changes the behavior of kprobes on ARM so that:
> 
>     Kprobes on conditional instructions don't trigger when the
>     condition is false. For conditional branches, this means that
>     they don't trigger in the branch not taken case.
> 
> Rationale:
> 
> When probes are placed onto conditionally executed instructions in a
> Thumb IT block, they may not fire if the condition is not met. This
> is because we use invalid instructions for breakpoints and "it is
> IMPLEMENTATION DEFINED whether the instruction executes as a NOP or
> causes an Undefined Instruction exception". Therefore, for consistency,
> we will ignore all probes on any conditional instructions when the
> condition is false. Alternative solutions seem to be too complex to
> implement or inconsistent.
> 
> This issue was discussed on linux.arm.kernel in the thread titled
> "[RFC] kprobes with thumb2 conditional code" See
> http://comments.gmane.org/gmane.linux.linaro.devel/2985
> 
> Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>

Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>

> ---
>  arch/arm/kernel/kprobes.c |   24 +++++++++++++++++++++++-
>  1 files changed, 23 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
> index b8f5b3b..7a9be60 100644
> --- a/arch/arm/kernel/kprobes.c
> +++ b/arch/arm/kernel/kprobes.c
> @@ -207,6 +207,20 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
>  	__get_cpu_var(current_kprobe) = p;
>  }
>  
> +static void __kprobes
> +singlestep_skip(struct kprobe *p, struct pt_regs *regs)
> +{
> +#ifdef CONFIG_THUMB2_KERNEL
> +	regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
> +	if (is_wide_instruction(p->opcode))
> +		regs->ARM_pc += 4;
> +	else
> +		regs->ARM_pc += 2;
> +#else
> +	regs->ARM_pc += 4;
> +#endif
> +}
> +
>  static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
>  				 struct kprobe_ctlblk *kcb)
>  {
> @@ -262,7 +276,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
>  				/* impossible cases */
>  				BUG();
>  			}
> -		} else {
> +		} else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
> +			/* Probe hit and conditional execution check ok. */
>  			set_current_kprobe(p);
>  			kcb->kprobe_status = KPROBE_HIT_ACTIVE;
>  
> @@ -282,6 +297,13 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
>  				}
>  				reset_current_kprobe();
>  			}
> +		} else {
> +			/*
> +			 * Probe hit but conditional execution check failed,
> +			 * so just skip the instruction and continue as if
> +			 * nothing had happened.
> +			 */
> +			singlestep_skip(p, regs);
>  		}
>  	} else if (cur) {
>  		/* We probably hit a jprobe.  Call its break handler. */
> -- 
> 1.7.2.5
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction
  2011-07-09 10:57 ` [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction Tixy
@ 2011-07-11 19:19   ` Nicolas Pitre
  0 siblings, 0 replies; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-11 19:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> --- a/arch/arm/kernel/kprobes.c
> +++ b/arch/arm/kernel/kprobes.c
> @@ -51,6 +51,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
>  	kprobe_opcode_t insn;
>  	kprobe_opcode_t tmp_insn[MAX_INSN_SIZE];
>  	unsigned long addr = (unsigned long)p->addr;
> +	bool thumb;
>  	kprobe_decode_insn_t *decode_insn;
>  	int is;
>  
> @@ -58,6 +59,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
>  		return -EINVAL;
>  
>  #ifdef CONFIG_THUMB2_KERNEL
> +	thumb = 1;

When using a bool variable, you might want to assign it with "true" or 
"false" rather than "1" and "0".


Nicolas

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions
  2011-07-09 10:57 ` [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions Tixy
@ 2011-07-11 20:05   ` Nicolas Pitre
  2011-07-12  7:14     ` Tixy
  0 siblings, 1 reply; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-11 20:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> +/*
> + * Prepare an instruction slot to receive an instruction for emulating.
> + * This is done by placing a subroutine return after the location where the
> + * instruction will be placed. We also modify ARM instructions to be
> + * unconditional as the condition code will already be checked before any
> + * emulation handler is called.
> + */
> +static kprobe_opcode_t __kprobes
> +prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> +								bool thumb)
> +{
> +#ifdef CONFIG_THUMB2_KERNEL
> +	if (thumb) {
> +		u16* thumb_insn = (u16 *)asi->insn;

Ninor style nit: we usually put the * against the variable rather than 
the type.  Here's why:

	u16* a, b, c;

vs

	u16 *a, b, c;

The first case is likely to cause confusion.

> +		thumb_insn[1] = 0x4770; /* Thumb bx lr */
> +		thumb_insn[2] = 0x4770; /* Thumb bx lr */
> +		return insn;
> +	}
> +	asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
> +#else
> +	asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
> +#endif
> +	/* Make an ARM instructional unconditional */

You meant "instruction" here I suppose.

Otherwise this looks really great.

Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>


Nicolas

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 37/51] ARM: kprobes: Optimise emulation of LDM and STM
  2011-07-09 10:57 ` [PATCH 37/51] ARM: kprobes: Optimise emulation of " Tixy
@ 2011-07-12  0:45   ` Nicolas Pitre
  2011-07-12  7:20     ` Tixy
  0 siblings, 1 reply; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-12  0:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> From: Jon Medhurst <tixy@yxit.co.uk>
> 
> This patch improves the performance of LDM and STM instruction
> emulation. This is desirable because.
> 
> - jprobes and kretprobes probe the first instruction in a function and,
>   when the frame pointer is omitted, this instruction is often a STM
>   used to push registers onto the stack.
> 
> - The STM and LDM instructions are common in the body and tail of
>   functions.
> 
> - At the same time as being a common instruction form, they also have
>   one of the slowest and most complicated simulation routines.
> 
> The approach taken to optimisation is to use simulation rather than
> emulation,

Isn't it the other way around i.e. emulation rather than simulation?

> +static void __kprobes
> +emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs)
> +{
> +	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2));
> +}
> +
> +static void __kprobes
> +emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs)
> +{
> +	emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3));
> +	load_write_pc(regs->ARM_pc, regs);
> +}

Pretty sneaky!  :-)

Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>


Nicolas

^ permalink raw reply	[flat|nested] 65+ messages in thread

* ARM: kprobes: Add support for Thumb-2
  2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
                   ` (50 preceding siblings ...)
  2011-07-09 10:57 ` [PATCH 51/51] ARM: kprobes: Decode 32-bit Thumb multiply and absolute difference instructions Tixy
@ 2011-07-12  1:02 ` Nicolas Pitre
  51 siblings, 0 replies; 65+ messages in thread
From: Nicolas Pitre @ 2011-07-12  1:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 9 Jul 2011, Tixy wrote:

> This patch series adds support for kprobes on Thumb-2 kernels.
> This requires making the framework handle Thumb breakpoints and adding
> simulation and emulation routines for the Thumb instruction set.
> 
> Note, this series also modifies the existing behaviour in the case when
> probes are placed on conditionally executed instructions (see patch 15).

Pretty nice and well organized patch series.  This is excellent work !

Although I didn't reply to all the patches, I've read them all and you 
can add "Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>" to all of 
them after the already posted comments are addressed.

I know that you also developed a comprehensive test suite in parallel to 
validate all this code.  I'm therefore pretty confident it'll work as 
well if not better than the existing code we had in the tree for quite a 
while before you started working on it.

I think this is ready to be merged with Russell whenever you are done 
with those small fixes.


Nicolas

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions
  2011-07-11 20:05   ` Nicolas Pitre
@ 2011-07-12  7:14     ` Tixy
  0 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-12  7:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-11 at 16:05 -0400, Nicolas Pitre wrote:
> On Sat, 9 Jul 2011, Tixy wrote:
> 
> > +static kprobe_opcode_t __kprobes
> > +prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
> > +								bool thumb)
> > +{
> > +#ifdef CONFIG_THUMB2_KERNEL
> > +	if (thumb) {
> > +		u16* thumb_insn = (u16 *)asi->insn;
> 
> Ninor style nit: we usually put the * against the variable rather than 
> the type.

checkpatch doesn't catch that one. I'll try and come up with a
simplified test case for a bug report.

-- 
Tixy

^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH 37/51] ARM: kprobes: Optimise emulation of LDM and STM
  2011-07-12  0:45   ` Nicolas Pitre
@ 2011-07-12  7:20     ` Tixy
  0 siblings, 0 replies; 65+ messages in thread
From: Tixy @ 2011-07-12  7:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 2011-07-11 at 20:45 -0400, Nicolas Pitre wrote: 
> On Sat, 9 Jul 2011, Tixy wrote:
> > The approach taken to optimisation is to use simulation rather than
> > emulation,
> 
> Isn't it the other way around i.e. emulation rather than simulation?

It is.

-- 
Tixy 

^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2011-07-12  7:20 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-09 10:56 ARM: kprobes: Add support for Thumb-2 Tixy
2011-07-09 10:56 ` [PATCH 01/51] ARM: Thumb-2: Fix exception return sequence to restore stack correctly Tixy
2011-07-11 18:07   ` Nicolas Pitre
2011-07-09 10:56 ` [PATCH 02/51] ARM: Thumb-2: Support Thumb-2 in undefined instruction handler Tixy
2011-07-11 18:14   ` Nicolas Pitre
2011-07-09 10:56 ` [PATCH 03/51] ARM: kprobes: Rename kprobes-decode.c to kprobes-arm.c Tixy
2011-07-09 10:56 ` [PATCH 04/51] ARM: kprobes: Split out internal parts of kprobes.h Tixy
2011-07-09 10:56 ` [PATCH 05/51] ARM: kprobes: Add kprobes-common.c Tixy
2011-07-09 10:56 ` [PATCH 06/51] ARM: kprobes: Move is_writeback define to header file Tixy
2011-07-09 10:56 ` [PATCH 07/51] ARM: kprobes: Move find_str_pc_offset into kprobes-common.c Tixy
2011-07-09 10:56 ` [PATCH 08/51] ARM: kprobes: Make str_pc_offset a constant on ARMv7 Tixy
2011-07-09 10:56 ` [PATCH 09/51] ARM: kprobes: Make kprobes framework work on Thumb-2 kernels Tixy
2011-07-09 10:56 ` [PATCH 10/51] ARM: kprobes: Add Thumb instruction decoding stubs Tixy
2011-07-09 10:56 ` [PATCH 11/51] ARM: Kconfig: Allow kprobes on Thumb-2 kernels Tixy
2011-07-11 11:01   ` Sergei Shtylyov
2011-07-11 11:33     ` Tixy
2011-07-11 11:42       ` Russell King - ARM Linux
2011-07-11 11:47         ` Tixy
2011-07-09 10:56 ` [PATCH 12/51] ARM: kprobes: Add Thumb breakpoint support Tixy
2011-07-09 10:57 ` [PATCH 13/51] ARM: kprobes: Add condition code checking to Thumb emulation Tixy
2011-07-09 10:57 ` [PATCH 14/51] ARM: kprobes: Add it_advance() Tixy
2011-07-09 10:57 ` [PATCH 15/51] ARM: kprobes: Don't trigger probes on conditional instructions when condition is false Tixy
2011-07-11 19:04   ` Nicolas Pitre
2011-07-09 10:57 ` [PATCH 16/51] ARM: kprobes: Use conditional breakpoints for ARM probes Tixy
2011-07-09 10:57 ` [PATCH 17/51] ARM: kprobes: Add hooks to override singlestep() Tixy
2011-07-09 10:57 ` [PATCH 18/51] ARM: kprobes: Extend arch_specific_insn to add pointer to emulated instruction Tixy
2011-07-11 19:19   ` Nicolas Pitre
2011-07-09 10:57 ` [PATCH 19/51] ARM: kprobes: Infrastructure for table driven decoding of CPU instructions Tixy
2011-07-11 20:05   ` Nicolas Pitre
2011-07-12  7:14     ` Tixy
2011-07-09 10:57 ` [PATCH 20/51] ARM: kprobes: Decode 16-bit Thumb hint instructions Tixy
2011-07-09 10:57 ` [PATCH 21/51] ARM: ptrace: Add APSR_MASK definition to ptrace.h Tixy
2011-07-09 10:57 ` [PATCH 22/51] ARM: kprobes: Decode 16-bit Thumb data-processing instructions Tixy
2011-07-09 10:57 ` [PATCH 23/51] ARM: kprobes: Add bx_write_pc() Tixy
2011-07-09 10:57 ` [PATCH 24/51] ARM: kprobes: Decode 16-bit Thumb BX and BLX instructions Tixy
2011-07-09 10:57 ` [PATCH 25/51] ARM: kprobes: Decode 16-bit Thumb special data instructions Tixy
2011-07-09 10:57 ` [PATCH 26/51] ARM: kprobes: Decode 16-bit Thumb load and store instructions Tixy
2011-07-09 10:57 ` [PATCH 27/51] ARM: kprobes: Decode 16-bit Thumb PC- and SP-relative address instructions Tixy
2011-07-09 10:57 ` [PATCH 28/51] ARM: kprobes: Decode 16-bit Thumb CBZ and bit manipulation instructions Tixy
2011-07-09 10:57 ` [PATCH 29/51] ARM: kprobes: Decode 16-bit Thumb PUSH and POP instructions Tixy
2011-07-09 10:57 ` [PATCH 30/51] ARM: kprobes: Decode 16-bit Thumb IT instruction Tixy
2011-07-09 10:57 ` [PATCH 31/51] ARM: kprobes: Reject 16-bit Thumb SVC and UNDEFINED instructions Tixy
2011-07-09 10:57 ` [PATCH 32/51] ARM: kprobes: Decode 16-bit Thumb branch instructions Tixy
2011-07-09 10:57 ` [PATCH 33/51] ARM: kprobes: Reject 16-bit Thumb SETEND, CPS and BKPT instructions Tixy
2011-07-09 10:57 ` [PATCH 34/51] ARM: kprobes: Decode 32-bit Thumb hint instructions Tixy
2011-07-09 10:57 ` [PATCH 35/51] ARM: kprobes: Add load_write_pc() Tixy
2011-07-09 10:57 ` [PATCH 36/51] ARM: kprobes: Add common decoding function for LDM and STM Tixy
2011-07-09 10:57 ` [PATCH 37/51] ARM: kprobes: Optimise emulation of " Tixy
2011-07-12  0:45   ` Nicolas Pitre
2011-07-12  7:20     ` Tixy
2011-07-09 10:57 ` [PATCH 38/51] ARM: kprobes: Decode 32-bit Thumb load/store multiple instructions Tixy
2011-07-09 10:57 ` [PATCH 39/51] ARM: kprobes: Decode 32-bit Thumb load/store dual and load/store exclusive instructions Tixy
2011-07-09 10:57 ` [PATCH 40/51] ARM: kprobes: Decode 32-bit Thumb table branch instructions Tixy
2011-07-09 10:57 ` [PATCH 41/51] ARM: kprobes: Decode 32-bit Thumb data-processing (shifted register) instructions Tixy
2011-07-09 10:57 ` [PATCH 42/51] ARM: kprobes: Decode 32-bit Thumb data-processing (modified immediate) instructions Tixy
2011-07-09 10:57 ` [PATCH 43/51] ARM: kprobes: Decode 32-bit Thumb data-processing (plain binary " Tixy
2011-07-09 10:57 ` [PATCH 44/51] ARM: kprobes: Decode 32-bit miscellaneous control instructions Tixy
2011-07-09 10:57 ` [PATCH 45/51] ARM: kprobes: Decode 32-bit Thumb branch instructions Tixy
2011-07-09 10:57 ` [PATCH 46/51] ARM: kprobes: Reject 32-bit Thumb coprocessor and SIMD instructions Tixy
2011-07-09 10:57 ` [PATCH 47/51] ARM: kprobes: Decode 32-bit Thumb memory hint instructions Tixy
2011-07-09 10:57 ` [PATCH 48/51] ARM: kprobes: Decode 32-bit Thumb load/store single data item instructions Tixy
2011-07-09 10:57 ` [PATCH 49/51] ARM: kprobes: Decode 32-bit Thumb data-processing (register) instructions Tixy
2011-07-09 10:57 ` [PATCH 50/51] ARM: kprobes: Decode 32-bit Thumb long multiply and divide instructions Tixy
2011-07-09 10:57 ` [PATCH 51/51] ARM: kprobes: Decode 32-bit Thumb multiply and absolute difference instructions Tixy
2011-07-12  1:02 ` ARM: kprobes: Add support for Thumb-2 Nicolas Pitre

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.