Skip to content

Commit ebc00dd

Browse files
esmilpalmer-dabbelt
authored andcommitted
riscv: Add jump-label implementation
Add jump-label implementation based on the ARM64 version and add CONFIG_JUMP_LABEL=y to the defconfigs. Signed-off-by: Emil Renner Berthing <[email protected]> Reviewed-by: Björn Töpel <[email protected]> Tested-by: Björn Töpel <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 11a54f4 commit ebc00dd

File tree

9 files changed

+122
-1
lines changed

9 files changed

+122
-1
lines changed

Documentation/features/core/jump-labels/arch-support.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
| openrisc: | TODO |
2424
| parisc: | ok |
2525
| powerpc: | ok |
26-
| riscv: | TODO |
26+
| riscv: | ok |
2727
| s390: | ok |
2828
| sh: | TODO |
2929
| sparc: | ok |

arch/riscv/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ config RISCV
4747
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
4848
select HANDLE_DOMAIN_IRQ
4949
select HAVE_ARCH_AUDITSYSCALL
50+
select HAVE_ARCH_JUMP_LABEL
51+
select HAVE_ARCH_JUMP_LABEL_RELATIVE
5052
select HAVE_ARCH_KASAN if MMU && 64BIT
5153
select HAVE_ARCH_KGDB
5254
select HAVE_ARCH_KGDB_QXFER_PKT

arch/riscv/configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
1717
CONFIG_SOC_SIFIVE=y
1818
CONFIG_SOC_VIRT=y
1919
CONFIG_SMP=y
20+
CONFIG_JUMP_LABEL=y
2021
CONFIG_MODULES=y
2122
CONFIG_MODULE_UNLOAD=y
2223
CONFIG_NET=y

arch/riscv/configs/nommu_k210_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ CONFIG_SMP=y
3333
CONFIG_NR_CPUS=2
3434
CONFIG_CMDLINE="earlycon console=ttySIF0"
3535
CONFIG_CMDLINE_FORCE=y
36+
CONFIG_JUMP_LABEL=y
3637
# CONFIG_BLOCK is not set
3738
CONFIG_BINFMT_FLAT=y
3839
# CONFIG_COREDUMP is not set

arch/riscv/configs/nommu_virt_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ CONFIG_MAXPHYSMEM_2GB=y
3030
CONFIG_SMP=y
3131
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
3232
CONFIG_CMDLINE_FORCE=y
33+
CONFIG_JUMP_LABEL=y
3334
# CONFIG_BLK_DEV_BSG is not set
3435
CONFIG_PARTITION_ADVANCED=y
3536
# CONFIG_MSDOS_PARTITION is not set

arch/riscv/configs/rv32_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
1717
CONFIG_SOC_VIRT=y
1818
CONFIG_ARCH_RV32I=y
1919
CONFIG_SMP=y
20+
CONFIG_JUMP_LABEL=y
2021
CONFIG_MODULES=y
2122
CONFIG_MODULE_UNLOAD=y
2223
CONFIG_NET=y

arch/riscv/include/asm/jump_label.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2020 Emil Renner Berthing
4+
*
5+
* Based on arch/arm64/include/asm/jump_label.h
6+
*/
7+
#ifndef __ASM_JUMP_LABEL_H
8+
#define __ASM_JUMP_LABEL_H
9+
10+
#ifndef __ASSEMBLY__
11+
12+
#include <linux/types.h>
13+
#include <asm/asm.h>
14+
15+
#define JUMP_LABEL_NOP_SIZE 4
16+
17+
static __always_inline bool arch_static_branch(struct static_key *key,
18+
bool branch)
19+
{
20+
asm_volatile_goto(
21+
" .option push \n\t"
22+
" .option norelax \n\t"
23+
" .option norvc \n\t"
24+
"1: nop \n\t"
25+
" .option pop \n\t"
26+
" .pushsection __jump_table, \"aw\" \n\t"
27+
" .align " RISCV_LGPTR " \n\t"
28+
" .long 1b - ., %l[label] - . \n\t"
29+
" " RISCV_PTR " %0 - . \n\t"
30+
" .popsection \n\t"
31+
: : "i"(&((char *)key)[branch]) : : label);
32+
33+
return false;
34+
label:
35+
return true;
36+
}
37+
38+
static __always_inline bool arch_static_branch_jump(struct static_key *key,
39+
bool branch)
40+
{
41+
asm_volatile_goto(
42+
" .option push \n\t"
43+
" .option norelax \n\t"
44+
" .option norvc \n\t"
45+
"1: jal zero, %l[label] \n\t"
46+
" .option pop \n\t"
47+
" .pushsection __jump_table, \"aw\" \n\t"
48+
" .align " RISCV_LGPTR " \n\t"
49+
" .long 1b - ., %l[label] - . \n\t"
50+
" " RISCV_PTR " %0 - . \n\t"
51+
" .popsection \n\t"
52+
: : "i"(&((char *)key)[branch]) : : label);
53+
54+
return false;
55+
label:
56+
return true;
57+
}
58+
59+
#endif /* __ASSEMBLY__ */
60+
#endif /* __ASM_JUMP_LABEL_H */

arch/riscv/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ endif
5353
obj-$(CONFIG_HOTPLUG_CPU) += cpu-hotplug.o
5454
obj-$(CONFIG_KGDB) += kgdb.o
5555

56+
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
57+
5658
clean:

arch/riscv/kernel/jump_label.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2020 Emil Renner Berthing
4+
*
5+
* Based on arch/arm64/kernel/jump_label.c
6+
*/
7+
#include <linux/jump_label.h>
8+
#include <linux/kernel.h>
9+
#include <linux/memory.h>
10+
#include <linux/mutex.h>
11+
#include <asm/bug.h>
12+
#include <asm/patch.h>
13+
14+
#define RISCV_INSN_NOP 0x00000013U
15+
#define RISCV_INSN_JAL 0x0000006fU
16+
17+
void arch_jump_label_transform(struct jump_entry *entry,
18+
enum jump_label_type type)
19+
{
20+
void *addr = (void *)jump_entry_code(entry);
21+
u32 insn;
22+
23+
if (type == JUMP_LABEL_JMP) {
24+
long offset = jump_entry_target(entry) - jump_entry_code(entry);
25+
26+
if (WARN_ON(offset & 1 || offset < -524288 || offset >= 524288))
27+
return;
28+
29+
insn = RISCV_INSN_JAL |
30+
(((u32)offset & GENMASK(19, 12)) << (12 - 12)) |
31+
(((u32)offset & GENMASK(11, 11)) << (20 - 11)) |
32+
(((u32)offset & GENMASK(10, 1)) << (21 - 1)) |
33+
(((u32)offset & GENMASK(20, 20)) << (31 - 20));
34+
} else {
35+
insn = RISCV_INSN_NOP;
36+
}
37+
38+
mutex_lock(&text_mutex);
39+
patch_text_nosync(addr, &insn, sizeof(insn));
40+
mutex_unlock(&text_mutex);
41+
}
42+
43+
void arch_jump_label_transform_static(struct jump_entry *entry,
44+
enum jump_label_type type)
45+
{
46+
/*
47+
* We use the same instructions in the arch_static_branch and
48+
* arch_static_branch_jump inline functions, so there's no
49+
* need to patch them up here.
50+
* The core will call arch_jump_label_transform when those
51+
* instructions need to be replaced.
52+
*/
53+
}

0 commit comments

Comments
 (0)