summaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/jump_label.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/include/asm/jump_label.h')
-rw-r--r--arch/mips/include/asm/jump_label.h42
1 files changed, 36 insertions, 6 deletions
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index 4d6d77ed9b9d..c1508f88e03e 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,9 +8,15 @@
#ifndef _ASM_MIPS_JUMP_LABEL_H
#define _ASM_MIPS_JUMP_LABEL_H
+#define arch_jump_label_transform_static arch_jump_label_transform
+
+#ifndef __ASSEMBLER__
+
#include <linux/types.h>
+#include <asm/isa-rev.h>
-#ifdef __KERNEL__
+struct module;
+extern void jump_label_apply_nops(struct module *mod);
#define JUMP_LABEL_NOP_SIZE 4
@@ -20,20 +26,43 @@
#define WORD_INSN ".word"
#endif
-static __always_inline bool arch_static_branch(struct static_key *key)
+#ifdef CONFIG_CPU_MICROMIPS
+# define B_INSN "b32"
+# define J_INSN "j32"
+#elif MIPS_ISA_REV >= 6
+# define B_INSN "bc"
+# define J_INSN "bc"
+#else
+# define B_INSN "b"
+# define J_INSN "j"
+#endif
+
+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
- asm goto("1:\tnop\n\t"
- "nop\n\t"
+ asm goto("1:\t" B_INSN " 2f\n\t"
+ "2:\t.insn\n\t"
".pushsection __jump_table, \"aw\"\n\t"
WORD_INSN " 1b, %l[l_yes], %0\n\t"
".popsection\n\t"
- : : "i" (key) : : l_yes);
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
return false;
l_yes:
return true;
}
-#endif /* __KERNEL__ */
+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+{
+ asm goto("1:\t" J_INSN " %l[l_yes]\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ WORD_INSN " 1b, %l[l_yes], %0\n\t"
+ ".popsection\n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
#ifdef CONFIG_64BIT
typedef u64 jump_label_t;
@@ -47,4 +76,5 @@ struct jump_entry {
jump_label_t key;
};
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_MIPS_JUMP_LABEL_H */