[PATCH -next V2 2/2] riscv: jump_label: Using c.j for CONFIG_RISCV_ISA_C

From: guoren
Date: Sat Dec 10 2022 - 05:10:12 EST


From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>

Reduce the size of the static branch instruction and prevent atomic
update problems. It would also reduce the range from 1MB to 4KB.
The range of 4K is enough for static branch.

Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx>
Signed-off-by: Guo Ren <guoren@xxxxxxxxxx>
Cc: Jessica Clarke <jrtc27@xxxxxxxxxx>
---
arch/riscv/include/asm/jump_label.h | 16 +++++++++++----
arch/riscv/kernel/jump_label.c | 30 +++++++++++++++++++++++++++--
2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/include/asm/jump_label.h b/arch/riscv/include/asm/jump_label.h
index 729991e8f782..e5f772ad5887 100644
--- a/arch/riscv/include/asm/jump_label.h
+++ b/arch/riscv/include/asm/jump_label.h
@@ -12,17 +12,23 @@
#include <linux/types.h>
#include <asm/asm.h>

+#ifdef CONFIG_RISCV_ISA_C
+#define JUMP_LABEL_NOP_SIZE 2
+#else
#define JUMP_LABEL_NOP_SIZE 4
+#endif

static __always_inline bool arch_static_branch(struct static_key *key,
bool branch)
{
asm_volatile_goto(
- " .align 2 \n\t"
" .option push \n\t"
" .option norelax \n\t"
- " .option norvc \n\t"
+#ifdef CONFIG_RISCV_ISA_C
+ "1: c.nop \n\t"
+#else
"1: nop \n\t"
+#endif
" .option pop \n\t"
" .pushsection __jump_table, \"aw\" \n\t"
" .align " RISCV_LGPTR " \n\t"
@@ -40,11 +46,13 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
bool branch)
{
asm_volatile_goto(
- " .align 2 \n\t"
" .option push \n\t"
" .option norelax \n\t"
- " .option norvc \n\t"
+#ifdef CONFIG_RISCV_ISA_C
+ "1: c.j %l[label] \n\t"
+#else
"1: jal zero, %l[label] \n\t"
+#endif
" .option pop \n\t"
" .pushsection __jump_table, \"aw\" \n\t"
" .align " RISCV_LGPTR " \n\t"
diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c
index e6694759dbd0..08f42c49e3a0 100644
--- a/arch/riscv/kernel/jump_label.c
+++ b/arch/riscv/kernel/jump_label.c
@@ -11,26 +11,52 @@
#include <asm/bug.h>
#include <asm/patch.h>

+#ifdef CONFIG_RISCV_ISA_C
+#define RISCV_INSN_NOP 0x0001U
+#define RISCV_INSN_C_J 0xa001U
+#else
#define RISCV_INSN_NOP 0x00000013U
#define RISCV_INSN_JAL 0x0000006fU
+#endif

void arch_jump_label_transform(struct jump_entry *entry,
enum jump_label_type type)
{
void *addr = (void *)jump_entry_code(entry);
+#ifdef CONFIG_RISCV_ISA_C
+ u16 insn;
+#else
u32 insn;
+#endif

if (type == JUMP_LABEL_JMP) {
long offset = jump_entry_target(entry) - jump_entry_code(entry);
-
- if (WARN_ON(offset & 1 || offset < -524288 || offset >= 524288))
+ if (WARN_ON(offset & 1 || offset < -2048 || offset >= 2048))
return;

+#ifdef CONFIG_RISCV_ISA_C
+ /*
+ * 001 | imm[11|4|9:8|10|6|7|3:1|5] 01 - C.J
+ */
+ insn = RISCV_INSN_C_J |
+ (((u16)offset & GENMASK(5, 5)) >> (5 - 2)) |
+ (((u16)offset & GENMASK(3, 1)) << (3 - 1)) |
+ (((u16)offset & GENMASK(7, 7)) >> (7 - 6)) |
+ (((u16)offset & GENMASK(6, 6)) << (7 - 6)) |
+ (((u16)offset & GENMASK(10, 10)) >> (10 - 8)) |
+ (((u16)offset & GENMASK(9, 8)) << (9 - 8)) |
+ (((u16)offset & GENMASK(4, 4)) << (11 - 4)) |
+ (((u16)offset & GENMASK(11, 11)) << (12 - 11));
+#else
+ /*
+ * imm[20|10:1|11|19:12] | rd | 1101111 - JAL
+ */
insn = RISCV_INSN_JAL |
(((u32)offset & GENMASK(19, 12)) << (12 - 12)) |
(((u32)offset & GENMASK(11, 11)) << (20 - 11)) |
(((u32)offset & GENMASK(10, 1)) << (21 - 1)) |
(((u32)offset & GENMASK(20, 20)) << (31 - 20));
+#endif
} else {
insn = RISCV_INSN_NOP;
}
--
2.36.1