From 09f05d8529ff4aa92311c1a55ce35ac98cb59b8c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sat, 18 Feb 2012 17:52:41 +0100 Subject: 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 Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/insn.h | 10 ++++++++++ arch/arm/kernel/jump_label.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 arch/arm/kernel/jump_label.c (limited to 'arch/arm/kernel') 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 +#include + +#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 -- cgit 1.4.1