diff options
author | Rabin Vincent <rabin@rab.in> | 2012-02-18 20:52:41 +0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-03-24 13:38:56 +0400 |
commit | 09f05d8529ff4aa92311c1a55ce35ac98cb59b8c (patch) | |
tree | 0196ddc9e80d74c8d3e3473bd7bc21b3e520c3d9 /arch/arm/kernel | |
parent | a9468f30b5eac6957c86aea97954553bfb7c1f18 (diff) | |
download | linux-09f05d8529ff4aa92311c1a55ce35ac98cb59b8c.tar.xz |
ARM: 7334/1: add jump label support
Add the arch-specific code to support jump labels for ARM and Thumb-2.
This code will only be activated on compilers that are capable of
building it. It has been tested with GCC 4.6 patched with the patch
from GCC bug 48637.
Cc: Jason Baron <jbaron@redhat.com>
Signed-off-by: Rabin Vincent <rabin@rab.in>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/insn.h | 10 | ||||
-rw-r--r-- | arch/arm/kernel/jump_label.c | 39 |
3 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 8c63ee8d3c48..1b7d9a390971 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o +obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o patch.o ifdef CONFIG_THUMB2_KERNEL diff --git a/arch/arm/kernel/insn.h b/arch/arm/kernel/insn.h index 994d60fd3ff5..e96065da4dae 100644 --- a/arch/arm/kernel/insn.h +++ b/arch/arm/kernel/insn.h @@ -1,6 +1,16 @@ #ifndef __ASM_ARM_INSN_H #define __ASM_ARM_INSN_H +static inline unsigned long +arm_gen_nop(void) +{ +#ifdef CONFIG_THUMB2_KERNEL + return 0xf3af8000; /* nop.w */ +#else + return 0xe1a00000; /* mov r0, r0 */ +#endif +} + unsigned long __arm_gen_branch(unsigned long pc, unsigned long addr, bool link); diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c new file mode 100644 index 000000000000..4ce4f789446d --- /dev/null +++ b/arch/arm/kernel/jump_label.c @@ -0,0 +1,39 @@ +#include <linux/kernel.h> +#include <linux/jump_label.h> + +#include "insn.h" +#include "patch.h" + +#ifdef HAVE_JUMP_LABEL + +static void __arch_jump_label_transform(struct jump_entry *entry, + enum jump_label_type type, + bool is_static) +{ + void *addr = (void *)entry->code; + unsigned int insn; + + if (type == JUMP_LABEL_ENABLE) + insn = arm_gen_branch(entry->code, entry->target); + else + insn = arm_gen_nop(); + + if (is_static) + __patch_text(addr, insn); + else + patch_text(addr, insn); +} + +void arch_jump_label_transform(struct jump_entry *entry, + enum jump_label_type type) +{ + __arch_jump_label_transform(entry, type, false); +} + +void arch_jump_label_transform_static(struct jump_entry *entry, + enum jump_label_type type) +{ + __arch_jump_label_transform(entry, type, true); +} + +#endif |