1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _ASM_S390_JUMP_LABEL_H 3 #define _ASM_S390_JUMP_LABEL_H 4 5 #define HAVE_JUMP_LABEL_BATCH 6 7 #ifndef __ASSEMBLER__ 8 9 #include <linux/types.h> 10 #include <linux/stringify.h> 11 12 #define JUMP_LABEL_NOP_SIZE 6 13 14 #ifdef CONFIG_CC_IS_CLANG 15 #define JUMP_LABEL_STATIC_KEY_CONSTRAINT "i" 16 #elif __GNUC__ < 9 17 #define JUMP_LABEL_STATIC_KEY_CONSTRAINT "X" 18 #else 19 #define JUMP_LABEL_STATIC_KEY_CONSTRAINT "jdd" 20 #endif 21 22 #define ARCH_JUMP_TABLE_ENTRY(key, label, local_label) \ 23 ".pushsection __jump_table,\"aw\"\n" \ 24 ".balign 8\n" \ 25 ".long " local_label "-.," label "-.\n" \ 26 ".quad " key "-.\n" \ 27 ".popsection\n" 28 29 /* 30 * We use a brcl 0,<offset> instruction for jump labels so it 31 * can be easily distinguished from a hotpatch generated instruction. 32 */ 33 #define ARCH_STATIC_BRANCH_ASM(key, label) \ 34 "0: brcl 0," label "\n" \ 35 ARCH_JUMP_TABLE_ENTRY(key, label, "0b") 36 37 #define ARCH_STATIC_BRANCH_JUMP_ASM(key, label) \ 38 "0: brcl 15," label "\n" \ 39 ARCH_JUMP_TABLE_ENTRY(key, label, "0b") 40 41 static __always_inline bool arch_static_branch(struct static_key *key, bool branch) 42 { 43 asm goto(ARCH_STATIC_BRANCH_ASM("%0+%1", "%l[label]") 44 : : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label); 45 return false; 46 label: 47 return true; 48 } 49 50 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) 51 { 52 asm goto(ARCH_STATIC_BRANCH_JUMP_ASM("%0+%1", "%l[label]") 53 : : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label); 54 return false; 55 label: 56 return true; 57 } 58 59 #endif /* __ASSEMBLER__ */ 60 #endif 61