1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* Copyright (C) 2018 Cadence Design Systems Inc. */ 3 4 #ifndef _ASM_XTENSA_JUMP_LABEL_H 5 #define _ASM_XTENSA_JUMP_LABEL_H 6 7 #ifndef __ASSEMBLY__ 8 9 #include <linux/types.h> 10 11 #define JUMP_LABEL_NOP_SIZE 3 12 13 static __always_inline bool arch_static_branch(struct static_key *key, 14 bool branch) 15 { 16 asm_volatile_goto("1:\n\t" 17 "_nop\n\t" 18 ".pushsection __jump_table, \"aw\"\n\t" 19 ".word 1b, %l[l_yes], %c0\n\t" 20 ".popsection\n\t" 21 : : "i" (&((char *)key)[branch]) : : l_yes); 22 23 return false; 24 l_yes: 25 return true; 26 } 27 28 static __always_inline bool arch_static_branch_jump(struct static_key *key, 29 bool branch) 30 { 31 /* 32 * Xtensa assembler will mark certain points in the code 33 * as unreachable, so that later assembler or linker relaxation 34 * passes could use them. A spot right after the J instruction 35 * is one such point. Assembler and/or linker may insert padding 36 * or literals here, breaking code flow in case the J instruction 37 * is later replaced with NOP. Put a label right after the J to 38 * make it reachable and wrap both into a no-transform block 39 * to avoid any assembler interference with this. 40 */ 41 asm_volatile_goto("1:\n\t" 42 ".begin no-transform\n\t" 43 "_j %l[l_yes]\n\t" 44 "2:\n\t" 45 ".end no-transform\n\t" 46 ".pushsection __jump_table, \"aw\"\n\t" 47 ".word 1b, %l[l_yes], %c0\n\t" 48 ".popsection\n\t" 49 : : "i" (&((char *)key)[branch]) : : l_yes); 50 51 return false; 52 l_yes: 53 return true; 54 } 55 56 typedef u32 jump_label_t; 57 58 struct jump_entry { 59 jump_label_t code; 60 jump_label_t target; 61 jump_label_t key; 62 }; 63 64 #endif /* __ASSEMBLY__ */ 65 #endif 66