Skip to content

Commit

Permalink
csky: Add jump-label implementation
Browse files Browse the repository at this point in the history
Add jump-label implementation for static branch

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Signed-off-by: Guo Ren <guoren@kernel.org>
  • Loading branch information
Guo Ren committed Jul 30, 2022
1 parent 01ab464 commit 4e8bb4b
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
2 changes: 2 additions & 0 deletions arch/csky/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 47 additions & 0 deletions arch/csky/include/asm/jump_label.h
Original file line number Diff line number Diff line change
@@ -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 */
1 change: 1 addition & 0 deletions arch/csky/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
54 changes: 54 additions & 0 deletions arch/csky/kernel/jump_label.c
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit 4e8bb4b

Please sign in to comment.