162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* Copyright (C) 2018 Cadence Design Systems Inc. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef _ASM_XTENSA_JUMP_LABEL_H 562306a36Sopenharmony_ci#define _ASM_XTENSA_JUMP_LABEL_H 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define JUMP_LABEL_NOP_SIZE 3 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic __always_inline bool arch_static_branch(struct static_key *key, 1462306a36Sopenharmony_ci bool branch) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci asm goto("1:\n\t" 1762306a36Sopenharmony_ci "_nop\n\t" 1862306a36Sopenharmony_ci ".pushsection __jump_table, \"aw\"\n\t" 1962306a36Sopenharmony_ci ".word 1b, %l[l_yes], %c0\n\t" 2062306a36Sopenharmony_ci ".popsection\n\t" 2162306a36Sopenharmony_ci : : "i" (&((char *)key)[branch]) : : l_yes); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci return false; 2462306a36Sopenharmony_cil_yes: 2562306a36Sopenharmony_ci return true; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic __always_inline bool arch_static_branch_jump(struct static_key *key, 2962306a36Sopenharmony_ci bool branch) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci /* 3262306a36Sopenharmony_ci * Xtensa assembler will mark certain points in the code 3362306a36Sopenharmony_ci * as unreachable, so that later assembler or linker relaxation 3462306a36Sopenharmony_ci * passes could use them. A spot right after the J instruction 3562306a36Sopenharmony_ci * is one such point. Assembler and/or linker may insert padding 3662306a36Sopenharmony_ci * or literals here, breaking code flow in case the J instruction 3762306a36Sopenharmony_ci * is later replaced with NOP. Put a label right after the J to 3862306a36Sopenharmony_ci * make it reachable and wrap both into a no-transform block 3962306a36Sopenharmony_ci * to avoid any assembler interference with this. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci asm goto("1:\n\t" 4262306a36Sopenharmony_ci ".begin no-transform\n\t" 4362306a36Sopenharmony_ci "_j %l[l_yes]\n\t" 4462306a36Sopenharmony_ci "2:\n\t" 4562306a36Sopenharmony_ci ".end no-transform\n\t" 4662306a36Sopenharmony_ci ".pushsection __jump_table, \"aw\"\n\t" 4762306a36Sopenharmony_ci ".word 1b, %l[l_yes], %c0\n\t" 4862306a36Sopenharmony_ci ".popsection\n\t" 4962306a36Sopenharmony_ci : : "i" (&((char *)key)[branch]) : : l_yes); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci return false; 5262306a36Sopenharmony_cil_yes: 5362306a36Sopenharmony_ci return true; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_citypedef u32 jump_label_t; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistruct jump_entry { 5962306a36Sopenharmony_ci jump_label_t code; 6062306a36Sopenharmony_ci jump_label_t target; 6162306a36Sopenharmony_ci jump_label_t key; 6262306a36Sopenharmony_ci}; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 6562306a36Sopenharmony_ci#endif 66