Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Guo Ren 4e8bb4ba 01ab4649

+104
+2
arch/csky/Kconfig
··· 40 40 select GX6605S_TIMER if CPU_CK610 41 41 select HAVE_ARCH_TRACEHOOK 42 42 select HAVE_ARCH_AUDITSYSCALL 43 + select HAVE_ARCH_JUMP_LABEL if !CPU_CK610 44 + select HAVE_ARCH_JUMP_LABEL_RELATIVE 43 45 select HAVE_ARCH_MMAP_RND_BITS 44 46 select HAVE_ARCH_SECCOMP_FILTER 45 47 select HAVE_CONTEXT_TRACKING
+47
arch/csky/include/asm/jump_label.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef __ASM_CSKY_JUMP_LABEL_H 4 + #define __ASM_CSKY_JUMP_LABEL_H 5 + 6 + #ifndef __ASSEMBLY__ 7 + 8 + #include <linux/types.h> 9 + 10 + #define JUMP_LABEL_NOP_SIZE 4 11 + 12 + static __always_inline bool arch_static_branch(struct static_key *key, 13 + bool branch) 14 + { 15 + asm_volatile_goto( 16 + "1: nop32 \n" 17 + " .pushsection __jump_table, \"aw\" \n" 18 + " .align 2 \n" 19 + " .long 1b - ., %l[label] - . \n" 20 + " .long %0 - . \n" 21 + " .popsection \n" 22 + : : "i"(&((char *)key)[branch]) : : label); 23 + 24 + return false; 25 + label: 26 + return true; 27 + } 28 + 29 + static __always_inline bool arch_static_branch_jump(struct static_key *key, 30 + bool branch) 31 + { 32 + asm_volatile_goto( 33 + "1: bsr32 %l[label] \n" 34 + " .pushsection __jump_table, \"aw\" \n" 35 + " .align 2 \n" 36 + " .long 1b - ., %l[label] - . \n" 37 + " .long %0 - . \n" 38 + " .popsection \n" 39 + : : "i"(&((char *)key)[branch]) : : label); 40 + 41 + return false; 42 + label: 43 + return true; 44 + } 45 + 46 + #endif /* __ASSEMBLY__ */ 47 + #endif /* __ASM_CSKY_JUMP_LABEL_H */
+1
arch/csky/kernel/Makefile
··· 13 13 obj-$(CONFIG_CSKY_PMU_V1) += perf_event.o 14 14 obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o 15 15 obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o 16 + obj-$(CONFIG_JUMP_LABEL) += jump_label.o 16 17 17 18 ifdef CONFIG_FUNCTION_TRACER 18 19 CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
+54
arch/csky/kernel/jump_label.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/jump_label.h> 4 + #include <linux/kernel.h> 5 + #include <linux/memory.h> 6 + #include <linux/mutex.h> 7 + #include <linux/uaccess.h> 8 + #include <asm/cacheflush.h> 9 + 10 + #define NOP32_HI 0xc400 11 + #define NOP32_LO 0x4820 12 + #define BSR_LINK 0xe000 13 + 14 + void arch_jump_label_transform(struct jump_entry *entry, 15 + enum jump_label_type type) 16 + { 17 + unsigned long addr = jump_entry_code(entry); 18 + u16 insn[2]; 19 + int ret = 0; 20 + 21 + if (type == JUMP_LABEL_JMP) { 22 + long offset = jump_entry_target(entry) - jump_entry_code(entry); 23 + 24 + if (WARN_ON(offset & 1 || offset < -67108864 || offset >= 67108864)) 25 + return; 26 + 27 + offset = offset >> 1; 28 + 29 + insn[0] = BSR_LINK | 30 + ((uint16_t)((unsigned long) offset >> 16) & 0x3ff); 31 + insn[1] = (uint16_t)((unsigned long) offset & 0xffff); 32 + } else { 33 + insn[0] = NOP32_HI; 34 + insn[1] = NOP32_LO; 35 + } 36 + 37 + ret = copy_to_kernel_nofault((void *)addr, insn, 4); 38 + WARN_ON(ret); 39 + 40 + flush_icache_range(addr, addr + 4); 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 + arch_jump_label_transform(entry, type); 54 + }