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