[RFC PATCH 22/25] kvx: Add support for jump labels

Yann Sionneau
2023-01-03T17:01:34Z

Add support for jump labels to kvx arch.

CC: Peter Zijlstra <peterz@infradead.org>
CC: Josh Poimboeuf <jpoimboe@kernel.org>
CC: Jason Baron <jbaron@akamai.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Ard Biesheuvel <ardb@kernel.org>
CC: linux-kernel@vger.kernel.org
Co-developed-by: Clement Leger <clement.leger@bootlin.com>
Signed-off-by: Clement Leger <clement.leger@bootlin.com>
Co-developed-by: Julian Vetter <jvetter@kalray.eu>
Signed-off-by: Julian Vetter <jvetter@kalray.eu>
Co-developed-by: Yann Sionneau <ysionneau@kalray.eu>
Signed-off-by: Yann Sionneau <ysionneau@kalray.eu>
---
arch/kvx/include/asm/jump_label.h | 59 +++++++++++++++++++++++++++++++
arch/kvx/kernel/jump_label.c | 34 ++++++++++++++++++
2 files changed, 93 insertions(+)
create mode 100644 arch/kvx/include/asm/jump_label.h
create mode 100644 arch/kvx/kernel/jump_label.c

diff --git a/arch/kvx/include/asm/jump_label.h b/arch/kvx/include/asm/jump_label.h
new file mode 100644
index 000000000000..5becccaad20c
--- /dev/null
+++ b/arch/kvx/include/asm/jump_label.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2017-2023 Kalray Inc.
+ * Author(s): Clement Leger
+ */
+
+#ifndef _ASM_KVX_JUMP_LABEL_H
+#define _ASM_KVX_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+#include <asm/insns_defs.h>
+
+#define JUMP_LABEL_NOP_SIZE (KVX_INSN_NOP_SIZE * KVX_INSN_SYLLABLE_WIDTH)
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+ bool branch)
+{
+ asm_volatile_goto("1:\n\t"
+ "nop\n\t"
+ ";;\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".dword 1b, %l[l_yes], %c0\n\t"
+ ".popsection\n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+static __always_inline bool arch_static_branch_jump(struct static_key *key,
+ bool branch)
+{
+ asm_volatile_goto("1:\n\t"
+ "goto %l[l_yes]\n\t"
+ ";;\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".dword 1b, %l[l_yes], %c0\n\t"
+ ".popsection\n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+typedef u64 jump_label_t;
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/kvx/kernel/jump_label.c b/arch/kvx/kernel/jump_label.c
new file mode 100644
index 000000000000..5a602dbdede0
--- /dev/null
+++ b/arch/kvx/kernel/jump_label.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2017-2023 Kalray Inc.
+ * Author(s): Clement Leger
+ */
+
+#include <linux/cpu.h>
+#include <linux/jump_label.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/stop_machine.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/insns.h>
+#include <asm/insns_defs.h>
+
+void arch_jump_label_transform(struct jump_entry *e,
+ enum jump_label_type type)
+{
+ s32 off = (jump_entry_target(e) - jump_entry_code(e));
+ u32 insn_code;
+ u32 *insn_addr = (u32 *) jump_entry_code(e);
+
+ if (type == JUMP_LABEL_JMP) {
+ BUG_ON(KVX_INSN_GOTO_PCREL27_CHECK(off));
+
+ KVX_INSN_GOTO(&insn_code, KVX_INSN_PARALLEL_EOB, off);
+ } else {
+ KVX_INSN_NOP(&insn_code, KVX_INSN_PARALLEL_EOB);
+ }
+
+ kvx_insns_write(&insn_code, JUMP_LABEL_NOP_SIZE, insn_addr);
+}
--
2.37.2