87a71cc6d146cef9c8eabc9e03e2fb270b697851
[linux-2.6-block.git] / arch / riscv / include / asm / jump_label.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2020 Emil Renner Berthing
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 __ASSEMBLY__
11
12 #include <linux/types.h>
13 #include <asm/asm.h>
14
15 #define HAVE_JUMP_LABEL_BATCH
16
17 #define JUMP_LABEL_NOP_SIZE 4
18
19 #define JUMP_TABLE_ENTRY(key, label)                    \
20         ".pushsection   __jump_table, \"aw\"    \n\t"   \
21         ".align         " RISCV_LGPTR "         \n\t"   \
22         ".long          1b - ., " label " - .   \n\t"   \
23         "" RISCV_PTR "  " key " - .             \n\t"   \
24         ".popsection                            \n\t"
25
26 /* This macro is also expanded on the Rust side. */
27 #define ARCH_STATIC_BRANCH_ASM(key, label)              \
28         "       .align          2               \n\t"   \
29         "       .option push                    \n\t"   \
30         "       .option norelax                 \n\t"   \
31         "       .option norvc                   \n\t"   \
32         "1:     nop                             \n\t"   \
33         "       .option pop                     \n\t"   \
34         JUMP_TABLE_ENTRY(key, label)
35
36 static __always_inline bool arch_static_branch(struct static_key * const key,
37                                                const bool branch)
38 {
39         asm goto(
40                 ARCH_STATIC_BRANCH_ASM("%0", "%l[label]")
41                 :  :  "i"(&((char *)key)[branch]) :  : label);
42
43         return false;
44 label:
45         return true;
46 }
47
48 #define ARCH_STATIC_BRANCH_JUMP_ASM(key, label)         \
49         "       .align          2               \n\t"   \
50         "       .option push                    \n\t"   \
51         "       .option norelax                 \n\t"   \
52         "       .option norvc                   \n\t"   \
53         "1:     j       " label "               \n\t" \
54         "       .option pop                     \n\t"   \
55         JUMP_TABLE_ENTRY(key, label)
56
57 static __always_inline bool arch_static_branch_jump(struct static_key * const key,
58                                                     const bool branch)
59 {
60         asm goto(
61                 ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]")
62                 :  :  "i"(&((char *)key)[branch]) :  : label);
63
64         return false;
65 label:
66         return true;
67 }
68
69 #endif  /* __ASSEMBLY__ */
70 #endif  /* __ASM_JUMP_LABEL_H */