jump_label.h (1976B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _ASM_ARC_JUMP_LABEL_H 3#define _ASM_ARC_JUMP_LABEL_H 4 5#ifndef __ASSEMBLY__ 6 7#include <linux/stringify.h> 8#include <linux/types.h> 9 10#define JUMP_LABEL_NOP_SIZE 4 11 12/* 13 * NOTE about '.balign 4': 14 * 15 * To make atomic update of patched instruction available we need to guarantee 16 * that this instruction doesn't cross L1 cache line boundary. 17 * 18 * As of today we simply align instruction which can be patched by 4 byte using 19 * ".balign 4" directive. In that case patched instruction is aligned with one 20 * 16-bit NOP_S if this is required. 21 * However 'align by 4' directive is much stricter than it actually required. 22 * It's enough that our 32-bit instruction don't cross L1 cache line boundary / 23 * L1 I$ fetch block boundary which can be achieved by using 24 * ".bundle_align_mode" assembler directive. That will save us from adding 25 * useless NOP_S padding in most of the cases. 26 * 27 * TODO: switch to ".bundle_align_mode" directive using whin it will be 28 * supported by ARC toolchain. 29 */ 30 31static __always_inline bool arch_static_branch(struct static_key *key, 32 bool branch) 33{ 34 asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" 35 "1: \n" 36 "nop \n" 37 ".pushsection __jump_table, \"aw\" \n" 38 ".word 1b, %l[l_yes], %c0 \n" 39 ".popsection \n" 40 : : "i" (&((char *)key)[branch]) : : l_yes); 41 42 return false; 43l_yes: 44 return true; 45} 46 47static __always_inline bool arch_static_branch_jump(struct static_key *key, 48 bool branch) 49{ 50 asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" 51 "1: \n" 52 "b %l[l_yes] \n" 53 ".pushsection __jump_table, \"aw\" \n" 54 ".word 1b, %l[l_yes], %c0 \n" 55 ".popsection \n" 56 : : "i" (&((char *)key)[branch]) : : l_yes); 57 58 return false; 59l_yes: 60 return true; 61} 62 63typedef u32 jump_label_t; 64 65struct jump_entry { 66 jump_label_t code; 67 jump_label_t target; 68 jump_label_t key; 69}; 70 71#endif /* __ASSEMBLY__ */ 72#endif