powerpc: Add jump label support
authorMichael Ellerman <michael@ellerman.id.au>
Wed, 29 Jun 2011 19:16:59 +0000 (19:16 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 1 Jul 2011 03:48:55 +0000 (13:48 +1000)
This patch adds support for the new "jump label" feature.

Unlike x86 and sparc we just merrily patch the code with no locks etc,
as far as I know this is safe, but I'm not really sure what the x86/sparc
code is protecting against so maybe it's not.

I also don't see any reason for us to implement the poke_early() routine,
even though sparc does.

[BenH: Updated the patch to upstream generic changes]

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/Kconfig
arch/powerpc/include/asm/jump_label.h [new file with mode: 0644]
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/jump_label.c [new file with mode: 0644]

index 2729c66..c15f2e6 100644 (file)
@@ -134,6 +134,7 @@ config PPC
        select GENERIC_IRQ_SHOW_LEVEL
        select HAVE_RCU_TABLE_FREE if SMP
        select HAVE_SYSCALL_TRACEPOINTS
+       select HAVE_ARCH_JUMP_LABEL
 
 config EARLY_PRINTK
        bool
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..1f780b9
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _ASM_POWERPC_JUMP_LABEL_H
+#define _ASM_POWERPC_JUMP_LABEL_H
+
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+
+#include <asm/feature-fixups.h>
+
+#define JUMP_ENTRY_TYPE                stringify_in_c(FTR_ENTRY_LONG)
+#define JUMP_LABEL_NOP_SIZE    4
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("1:\n\t"
+                "nop\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".align 4\n\t"
+                JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
+                ".popsection \n\t"
+                : :  "i" (key) : : l_yes);
+       return false;
+l_yes:
+       return true;
+}
+
+#ifdef CONFIG_PPC64
+typedef u64 jump_label_t;
+#else
+typedef u32 jump_label_t;
+#endif
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+       jump_label_t pad;
+};
+
+#endif /* _ASM_POWERPC_JUMP_LABEL_H */
index e8b9818..ce4f7f1 100644 (file)
@@ -76,6 +76,7 @@ obj-$(CONFIG_MODULES)         += module.o module_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_44x)              += cpu_setup_44x.o
 obj-$(CONFIG_PPC_FSL_BOOK3E)   += cpu_setup_fsl_booke.o dbell.o
 obj-$(CONFIG_PPC_BOOK3E_64)    += dbell.o
+obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
 
 extra-y                                := head_$(CONFIG_WORD_SIZE).o
 extra-$(CONFIG_40x)            := head_40x.o
diff --git a/arch/powerpc/kernel/jump_label.c b/arch/powerpc/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..368d158
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 Michael Ellerman, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/jump_label.h>
+#include <asm/code-patching.h>
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       u32 *addr = (u32 *)(unsigned long)entry->code;
+
+       if (type == JUMP_LABEL_ENABLE)
+               patch_branch(addr, entry->target, 0);
+       else
+               patch_instruction(addr, PPC_INST_NOP);
+}