xref: /linux/arch/openrisc/include/asm/jump_label.h (revision 742adaa16db994ba1748465b95548e2f28aa18ca)
1*8c30b001Schenmiao /* SPDX-License-Identifier: GPL-2.0-only */
2*8c30b001Schenmiao /*
3*8c30b001Schenmiao  * Copyright (C) 2025 Chen Miao
4*8c30b001Schenmiao  *
5*8c30b001Schenmiao  * Based on arch/arm/include/asm/jump_label.h
6*8c30b001Schenmiao  */
7*8c30b001Schenmiao #ifndef __ASM_OPENRISC_JUMP_LABEL_H
8*8c30b001Schenmiao #define __ASM_OPENRISC_JUMP_LABEL_H
9*8c30b001Schenmiao 
10*8c30b001Schenmiao #ifndef __ASSEMBLER__
11*8c30b001Schenmiao 
12*8c30b001Schenmiao #include <linux/types.h>
13*8c30b001Schenmiao #include <asm/insn-def.h>
14*8c30b001Schenmiao 
15*8c30b001Schenmiao #define HAVE_JUMP_LABEL_BATCH
16*8c30b001Schenmiao 
17*8c30b001Schenmiao #define JUMP_LABEL_NOP_SIZE OPENRISC_INSN_SIZE
18*8c30b001Schenmiao 
19*8c30b001Schenmiao /**
20*8c30b001Schenmiao  * JUMP_TABLE_ENTRY - Create a jump table entry
21*8c30b001Schenmiao  * @key: Jump key identifier (typically a symbol address)
22*8c30b001Schenmiao  * @label: Target label address
23*8c30b001Schenmiao  *
24*8c30b001Schenmiao  * This macro creates a jump table entry in the dedicated kernel section (__jump_table).
25*8c30b001Schenmiao  * Each entry contains the following information:
26*8c30b001Schenmiao  * 		Offset from current instruction to jump instruction (1b - .)
27*8c30b001Schenmiao  * 		Offset from current instruction to target label (label - .)
28*8c30b001Schenmiao  * 		Offset from current instruction to key identifier (key - .)
29*8c30b001Schenmiao  */
30*8c30b001Schenmiao #define JUMP_TABLE_ENTRY(key, label)			\
31*8c30b001Schenmiao 	".pushsection	__jump_table, \"aw\"	\n\t"	\
32*8c30b001Schenmiao 	".align 	4 			\n\t"	\
33*8c30b001Schenmiao 	".long 		1b - ., " label " - .	\n\t"	\
34*8c30b001Schenmiao 	".long 		" key " - . 		\n\t"	\
35*8c30b001Schenmiao 	".popsection				\n\t"
36*8c30b001Schenmiao 
37*8c30b001Schenmiao #define ARCH_STATIC_BRANCH_ASM(key, label)		\
38*8c30b001Schenmiao 	".align		4			\n\t"	\
39*8c30b001Schenmiao 	"1: l.nop				\n\t"	\
40*8c30b001Schenmiao 	"    l.nop				\n\t"	\
41*8c30b001Schenmiao 	JUMP_TABLE_ENTRY(key, label)
42*8c30b001Schenmiao 
arch_static_branch(struct static_key * const key,const bool branch)43*8c30b001Schenmiao static __always_inline bool arch_static_branch(struct static_key *const key,
44*8c30b001Schenmiao 					       const bool branch)
45*8c30b001Schenmiao {
46*8c30b001Schenmiao 	asm goto (ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
47*8c30b001Schenmiao 		  ::"i"(&((char *)key)[branch])::l_yes);
48*8c30b001Schenmiao 
49*8c30b001Schenmiao 	return false;
50*8c30b001Schenmiao l_yes:
51*8c30b001Schenmiao 	return true;
52*8c30b001Schenmiao }
53*8c30b001Schenmiao 
54*8c30b001Schenmiao #define ARCH_STATIC_BRANCH_JUMP_ASM(key, label)		\
55*8c30b001Schenmiao 	".align		4			\n\t"	\
56*8c30b001Schenmiao 	"1: l.j	" label "			\n\t"	\
57*8c30b001Schenmiao 	"    l.nop				\n\t"	\
58*8c30b001Schenmiao 	JUMP_TABLE_ENTRY(key, label)
59*8c30b001Schenmiao 
60*8c30b001Schenmiao static __always_inline bool
arch_static_branch_jump(struct static_key * const key,const bool branch)61*8c30b001Schenmiao arch_static_branch_jump(struct static_key *const key, const bool branch)
62*8c30b001Schenmiao {
63*8c30b001Schenmiao 	asm goto (ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[l_yes]")
64*8c30b001Schenmiao 		  ::"i"(&((char *)key)[branch])::l_yes);
65*8c30b001Schenmiao 
66*8c30b001Schenmiao 	return false;
67*8c30b001Schenmiao l_yes:
68*8c30b001Schenmiao 	return true;
69*8c30b001Schenmiao }
70*8c30b001Schenmiao 
71*8c30b001Schenmiao #endif /* __ASSEMBLER__ */
72*8c30b001Schenmiao #endif /* __ASM_OPENRISC_JUMP_LABEL_H */
73