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
@ -23,7 +23,7 @@
|
||||
| openrisc: | TODO |
|
||||
| parisc: | ok |
|
||||
| powerpc: | ok |
|
||||
| riscv: | TODO |
|
||||
| riscv: | ok |
|
||||
| s390: | ok |
|
||||
| sh: | TODO |
|
||||
| sparc: | ok |
|
||||
|
@ -47,6 +47,8 @@ config RISCV
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
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_KGDB
|
||||
select HAVE_ARCH_KGDB_QXFER_PKT
|
||||
|
@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_SOC_SIFIVE=y
|
||||
CONFIG_SOC_VIRT=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
CONFIG_NET=y
|
||||
|
@ -33,6 +33,7 @@ CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_CMDLINE="earlycon console=ttySIF0"
|
||||
CONFIG_CMDLINE_FORCE=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
# CONFIG_BLOCK is not set
|
||||
CONFIG_BINFMT_FLAT=y
|
||||
# CONFIG_COREDUMP is not set
|
||||
|
@ -30,6 +30,7 @@ CONFIG_MAXPHYSMEM_2GB=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x10000000,115200n8 console=ttyS0"
|
||||
CONFIG_CMDLINE_FORCE=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
# CONFIG_MSDOS_PARTITION is not set
|
||||
|
@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_SOC_VIRT=y
|
||||
CONFIG_ARCH_RV32I=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=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_KGDB) += kgdb.o
|
||||
|
||||
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
|
||||
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…
Reference in New Issue
Block a user