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 <kernel@esmil.dk> Reviewed-by: Björn Töpel <bjorn.topel@gmail.com> Tested-by: Björn Töpel <bjorn.topel@gmail.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
This commit is contained in:
parent
11a54f422b
commit
ebc00dde8a
9 changed files with 122 additions and 1 deletions
|
@ -23,7 +23,7 @@
|
||||||
| openrisc: | TODO |
|
| openrisc: | TODO |
|
||||||
| parisc: | ok |
|
| parisc: | ok |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | ok |
|
||||||
| s390: | ok |
|
| s390: | ok |
|
||||||
| sh: | TODO |
|
| sh: | TODO |
|
||||||
| sparc: | ok |
|
| sparc: | ok |
|
||||||
|
|
|
@ -47,6 +47,8 @@ config RISCV
|
||||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||||
select HANDLE_DOMAIN_IRQ
|
select HANDLE_DOMAIN_IRQ
|
||||||
select HAVE_ARCH_AUDITSYSCALL
|
select HAVE_ARCH_AUDITSYSCALL
|
||||||
|
select HAVE_ARCH_JUMP_LABEL
|
||||||
|
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||||
select HAVE_ARCH_KASAN if MMU && 64BIT
|
select HAVE_ARCH_KASAN if MMU && 64BIT
|
||||||
select HAVE_ARCH_KGDB
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_ARCH_KGDB_QXFER_PKT
|
select HAVE_ARCH_KGDB_QXFER_PKT
|
||||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
|
||||||
CONFIG_SOC_SIFIVE=y
|
CONFIG_SOC_SIFIVE=y
|
||||||
CONFIG_SOC_VIRT=y
|
CONFIG_SOC_VIRT=y
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
|
CONFIG_JUMP_LABEL=y
|
||||||
CONFIG_MODULES=y
|
CONFIG_MODULES=y
|
||||||
CONFIG_MODULE_UNLOAD=y
|
CONFIG_MODULE_UNLOAD=y
|
||||||
CONFIG_NET=y
|
CONFIG_NET=y
|
||||||
|
|
|
@ -33,6 +33,7 @@ CONFIG_SMP=y
|
||||||
CONFIG_NR_CPUS=2
|
CONFIG_NR_CPUS=2
|
||||||
CONFIG_CMDLINE="earlycon console=ttySIF0"
|
CONFIG_CMDLINE="earlycon console=ttySIF0"
|
||||||
CONFIG_CMDLINE_FORCE=y
|
CONFIG_CMDLINE_FORCE=y
|
||||||
|
CONFIG_JUMP_LABEL=y
|
||||||
# CONFIG_BLOCK is not set
|
# CONFIG_BLOCK is not set
|
||||||
CONFIG_BINFMT_FLAT=y
|
CONFIG_BINFMT_FLAT=y
|
||||||
# CONFIG_COREDUMP is not set
|
# CONFIG_COREDUMP is not set
|
||||||
|
|
|
@ -30,6 +30,7 @@ CONFIG_MAXPHYSMEM_2GB=y
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
|
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
|
||||||
CONFIG_CMDLINE_FORCE=y
|
CONFIG_CMDLINE_FORCE=y
|
||||||
|
CONFIG_JUMP_LABEL=y
|
||||||
# CONFIG_BLK_DEV_BSG is not set
|
# CONFIG_BLK_DEV_BSG is not set
|
||||||
CONFIG_PARTITION_ADVANCED=y
|
CONFIG_PARTITION_ADVANCED=y
|
||||||
# CONFIG_MSDOS_PARTITION is not set
|
# CONFIG_MSDOS_PARTITION is not set
|
||||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
|
||||||
CONFIG_SOC_VIRT=y
|
CONFIG_SOC_VIRT=y
|
||||||
CONFIG_ARCH_RV32I=y
|
CONFIG_ARCH_RV32I=y
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
|
CONFIG_JUMP_LABEL=y
|
||||||
CONFIG_MODULES=y
|
CONFIG_MODULES=y
|
||||||
CONFIG_MODULE_UNLOAD=y
|
CONFIG_MODULE_UNLOAD=y
|
||||||
CONFIG_NET=y
|
CONFIG_NET=y
|
||||||
|
|
60
arch/riscv/include/asm/jump_label.h
Normal file
60
arch/riscv/include/asm/jump_label.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Emil Renner Berthing
|
||||||
|
*
|
||||||
|
* Based on arch/arm64/include/asm/jump_label.h
|
||||||
|
*/
|
||||||
|
#ifndef __ASM_JUMP_LABEL_H
|
||||||
|
#define __ASM_JUMP_LABEL_H
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/asm.h>
|
||||||
|
|
||||||
|
#define JUMP_LABEL_NOP_SIZE 4
|
||||||
|
|
||||||
|
static __always_inline bool arch_static_branch(struct static_key *key,
|
||||||
|
bool branch)
|
||||||
|
{
|
||||||
|
asm_volatile_goto(
|
||||||
|
" .option push \n\t"
|
||||||
|
" .option norelax \n\t"
|
||||||
|
" .option norvc \n\t"
|
||||||
|
"1: nop \n\t"
|
||||||
|
" .option pop \n\t"
|
||||||
|
" .pushsection __jump_table, \"aw\" \n\t"
|
||||||
|
" .align " RISCV_LGPTR " \n\t"
|
||||||
|
" .long 1b - ., %l[label] - . \n\t"
|
||||||
|
" " RISCV_PTR " %0 - . \n\t"
|
||||||
|
" .popsection \n\t"
|
||||||
|
: : "i"(&((char *)key)[branch]) : : label);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
label:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __always_inline bool arch_static_branch_jump(struct static_key *key,
|
||||||
|
bool branch)
|
||||||
|
{
|
||||||
|
asm_volatile_goto(
|
||||||
|
" .option push \n\t"
|
||||||
|
" .option norelax \n\t"
|
||||||
|
" .option norvc \n\t"
|
||||||
|
"1: jal zero, %l[label] \n\t"
|
||||||
|
" .option pop \n\t"
|
||||||
|
" .pushsection __jump_table, \"aw\" \n\t"
|
||||||
|
" .align " RISCV_LGPTR " \n\t"
|
||||||
|
" .long 1b - ., %l[label] - . \n\t"
|
||||||
|
" " RISCV_PTR " %0 - . \n\t"
|
||||||
|
" .popsection \n\t"
|
||||||
|
: : "i"(&((char *)key)[branch]) : : label);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
label:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ASSEMBLY__ */
|
||||||
|
#endif /* __ASM_JUMP_LABEL_H */
|
|
@ -53,4 +53,6 @@ endif
|
||||||
obj-$(CONFIG_HOTPLUG_CPU) += cpu-hotplug.o
|
obj-$(CONFIG_HOTPLUG_CPU) += cpu-hotplug.o
|
||||||
obj-$(CONFIG_KGDB) += kgdb.o
|
obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
53
arch/riscv/kernel/jump_label.c
Normal file
53
arch/riscv/kernel/jump_label.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Emil Renner Berthing
|
||||||
|
*
|
||||||
|
* Based on arch/arm64/kernel/jump_label.c
|
||||||
|
*/
|
||||||
|
#include <linux/jump_label.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/memory.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <asm/bug.h>
|
||||||
|
#include <asm/patch.h>
|
||||||
|
|
||||||
|
#define RISCV_INSN_NOP 0x00000013U
|
||||||
|
#define RISCV_INSN_JAL 0x0000006fU
|
||||||
|
|
||||||
|
void arch_jump_label_transform(struct jump_entry *entry,
|
||||||
|
enum jump_label_type type)
|
||||||
|
{
|
||||||
|
void *addr = (void *)jump_entry_code(entry);
|
||||||
|
u32 insn;
|
||||||
|
|
||||||
|
if (type == JUMP_LABEL_JMP) {
|
||||||
|
long offset = jump_entry_target(entry) - jump_entry_code(entry);
|
||||||
|
|
||||||
|
if (WARN_ON(offset & 1 || offset < -524288 || offset >= 524288))
|
||||||
|
return;
|
||||||
|
|
||||||
|
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));
|
||||||
|
} else {
|
||||||
|
insn = RISCV_INSN_NOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&text_mutex);
|
||||||
|
patch_text_nosync(addr, &insn, sizeof(insn));
|
||||||
|
mutex_unlock(&text_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_jump_label_transform_static(struct jump_entry *entry,
|
||||||
|
enum jump_label_type type)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We use the same instructions in the arch_static_branch and
|
||||||
|
* arch_static_branch_jump inline functions, so there's no
|
||||||
|
* need to patch them up here.
|
||||||
|
* The core will call arch_jump_label_transform when those
|
||||||
|
* instructions need to be replaced.
|
||||||
|
*/
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue