xref: /linux/arch/loongarch/include/asm/jump_label.h (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2023 Loongson Technology Corporation Limited
4  *
5  * Based on arch/arm64/include/asm/jump_label.h
6  */
7 #ifndef __ASM_JUMP_LABEL_H
8 #define __ASM_JUMP_LABEL_H
9 
10 #ifndef __ASSEMBLER__
11 
12 #include <linux/types.h>
13 #include <linux/stringify.h>
14 #include <asm/asm.h>
15 
16 #define JUMP_LABEL_NOP_SIZE	4
17 
18 #ifdef CONFIG_32BIT
19 #define JUMP_LABEL_TYPE		".long "
20 #else
21 #define JUMP_LABEL_TYPE		".quad "
22 #endif
23 
24 /* This macro is also expanded on the Rust side. */
25 #define JUMP_TABLE_ENTRY(key, label)			\
26 	 ".pushsection	__jump_table, \"aw\"	\n\t"	\
27 	 ".align	" __stringify(PTRLOG) "	\n\t"	\
28 	 ".long		1b - ., " label " - .	\n\t"	\
29 	 JUMP_LABEL_TYPE  key " - .		\n\t"	\
30 	 ".popsection				\n\t"
31 
32 #define ARCH_STATIC_BRANCH_ASM(key, label)		\
33 	"1:	nop				\n\t"	\
34 	JUMP_TABLE_ENTRY(key, label)
35 
36 static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
37 {
38 	asm goto(
39 		ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
40 		:  :  "i"(&((char *)key)[branch]) :  : l_yes);
41 
42 	return false;
43 
44 l_yes:
45 	return true;
46 }
47 
48 static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
49 {
50 	asm goto(
51 		"1:	b	%l[l_yes]	\n\t"
52 		JUMP_TABLE_ENTRY("%0", "%l[l_yes]")
53 		:  :  "i"(&((char *)key)[branch]) :  : l_yes);
54 
55 	return false;
56 
57 l_yes:
58 	return true;
59 }
60 
61 #endif  /* __ASSEMBLER__ */
62 #endif	/* __ASM_JUMP_LABEL_H */
63