csky: Add jump-label implementation
Add jump-label implementation for static branch Signed-off-by: Guo Ren <guoren@linux.alibaba.com> Signed-off-by: Guo Ren <guoren@kernel.org>
This commit is contained in:
parent
01ab4649ef
commit
4e8bb4ba5a
|
@ -40,6 +40,8 @@ config CSKY
|
|||
select GX6605S_TIMER if CPU_CK610
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !CPU_CK610
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_MMAP_RND_BITS
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_CONTEXT_TRACKING
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ASM_CSKY_JUMP_LABEL_H
|
||||
#define __ASM_CSKY_JUMP_LABEL_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define JUMP_LABEL_NOP_SIZE 4
|
||||
|
||||
static __always_inline bool arch_static_branch(struct static_key *key,
|
||||
bool branch)
|
||||
{
|
||||
asm_volatile_goto(
|
||||
"1: nop32 \n"
|
||||
" .pushsection __jump_table, \"aw\" \n"
|
||||
" .align 2 \n"
|
||||
" .long 1b - ., %l[label] - . \n"
|
||||
" .long %0 - . \n"
|
||||
" .popsection \n"
|
||||
: : "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(
|
||||
"1: bsr32 %l[label] \n"
|
||||
" .pushsection __jump_table, \"aw\" \n"
|
||||
" .align 2 \n"
|
||||
" .long 1b - ., %l[label] - . \n"
|
||||
" .long %0 - . \n"
|
||||
" .popsection \n"
|
||||
: : "i"(&((char *)key)[branch]) : : label);
|
||||
|
||||
return false;
|
||||
label:
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_CSKY_JUMP_LABEL_H */
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
|||
obj-$(CONFIG_CSKY_PMU_V1) += perf_event.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
||||
obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
|
||||
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <linux/jump_label.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/memory.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#define NOP32_HI 0xc400
|
||||
#define NOP32_LO 0x4820
|
||||
#define BSR_LINK 0xe000
|
||||
|
||||
void arch_jump_label_transform(struct jump_entry *entry,
|
||||
enum jump_label_type type)
|
||||
{
|
||||
unsigned long addr = jump_entry_code(entry);
|
||||
u16 insn[2];
|
||||
int ret = 0;
|
||||
|
||||
if (type == JUMP_LABEL_JMP) {
|
||||
long offset = jump_entry_target(entry) - jump_entry_code(entry);
|
||||
|
||||
if (WARN_ON(offset & 1 || offset < -67108864 || offset >= 67108864))
|
||||
return;
|
||||
|
||||
offset = offset >> 1;
|
||||
|
||||
insn[0] = BSR_LINK |
|
||||
((uint16_t)((unsigned long) offset >> 16) & 0x3ff);
|
||||
insn[1] = (uint16_t)((unsigned long) offset & 0xffff);
|
||||
} else {
|
||||
insn[0] = NOP32_HI;
|
||||
insn[1] = NOP32_LO;
|
||||
}
|
||||
|
||||
ret = copy_to_kernel_nofault((void *)addr, insn, 4);
|
||||
WARN_ON(ret);
|
||||
|
||||
flush_icache_range(addr, addr + 4);
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
arch_jump_label_transform(entry, type);
|
||||
}
|
Loading…
Reference in New Issue