1e6d6c071SJosh Poimboeuf /* SPDX-License-Identifier: GPL-2.0 */ 2e6d6c071SJosh Poimboeuf #ifndef _ASM_STATIC_CALL_H 3e6d6c071SJosh Poimboeuf #define _ASM_STATIC_CALL_H 4e6d6c071SJosh Poimboeuf 5e6d6c071SJosh Poimboeuf #include <asm/text-patching.h> 6e6d6c071SJosh Poimboeuf 7e6d6c071SJosh Poimboeuf /* 81e7e4788SJosh Poimboeuf * For CONFIG_HAVE_STATIC_CALL_INLINE, this is a temporary trampoline which 91e7e4788SJosh Poimboeuf * uses the current value of the key->func pointer to do an indirect jump to 101e7e4788SJosh Poimboeuf * the function. This trampoline is only used during boot, before the call 111e7e4788SJosh Poimboeuf * sites get patched by static_call_update(). The name of this trampoline has 121e7e4788SJosh Poimboeuf * a magical aspect: objtool uses it to find static call sites so it can create 131e7e4788SJosh Poimboeuf * the .static_call_sites section. 141e7e4788SJosh Poimboeuf * 15e6d6c071SJosh Poimboeuf * For CONFIG_HAVE_STATIC_CALL, this is a permanent trampoline which 16e6d6c071SJosh Poimboeuf * does a direct jump to the function. The direct jump gets patched by 17e6d6c071SJosh Poimboeuf * static_call_update(). 181e7e4788SJosh Poimboeuf * 191e7e4788SJosh Poimboeuf * Having the trampoline in a special section forces GCC to emit a JMP.d32 when 201e7e4788SJosh Poimboeuf * it does tail-call optimization on the call; since you cannot compute the 211e7e4788SJosh Poimboeuf * relative displacement across sections. 22e6d6c071SJosh Poimboeuf */ 23452cddbfSPeter Zijlstra 24ee88d363SPeter Zijlstra /* 25ee88d363SPeter Zijlstra * The trampoline is 8 bytes and of the general form: 26ee88d363SPeter Zijlstra * 27ee88d363SPeter Zijlstra * jmp.d32 \func 28ee88d363SPeter Zijlstra * ud1 %esp, %ecx 29ee88d363SPeter Zijlstra * 30ee88d363SPeter Zijlstra * That trailing #UD provides both a speculation stop and serves as a unique 31ee88d363SPeter Zijlstra * 3 byte signature identifying static call trampolines. Also see tramp_ud[] 32ee88d363SPeter Zijlstra * and __static_call_fixup(). 33ee88d363SPeter Zijlstra */ 34452cddbfSPeter Zijlstra #define __ARCH_DEFINE_STATIC_CALL_TRAMP(name, insns) \ 351e7e4788SJosh Poimboeuf asm(".pushsection .static_call.text, \"ax\" \n" \ 36e6d6c071SJosh Poimboeuf ".align 4 \n" \ 37e6d6c071SJosh Poimboeuf ".globl " STATIC_CALL_TRAMP_STR(name) " \n" \ 38e6d6c071SJosh Poimboeuf STATIC_CALL_TRAMP_STR(name) ": \n" \ 39613871cdSJosh Poimboeuf ANNOTATE_NOENDBR \ 40452cddbfSPeter Zijlstra insns " \n" \ 41ee88d363SPeter Zijlstra ".byte 0x0f, 0xb9, 0xcc \n" \ 42e6d6c071SJosh Poimboeuf ".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \ 43e6d6c071SJosh Poimboeuf ".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \ 44e6d6c071SJosh Poimboeuf ".popsection \n") 45e6d6c071SJosh Poimboeuf 46452cddbfSPeter Zijlstra #define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) \ 47452cddbfSPeter Zijlstra __ARCH_DEFINE_STATIC_CALL_TRAMP(name, ".byte 0xe9; .long " #func " - (. + 4)") 48452cddbfSPeter Zijlstra 49*0911b8c5SBreno Leitao #ifdef CONFIG_MITIGATION_RETHUNK 50ee88d363SPeter Zijlstra #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \ 51ee88d363SPeter Zijlstra __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "jmp __x86_return_thunk") 52ee88d363SPeter Zijlstra #else 53452cddbfSPeter Zijlstra #define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) \ 54e463a09aSPeter Zijlstra __ARCH_DEFINE_STATIC_CALL_TRAMP(name, "ret; int3; nop; nop; nop") 55ee88d363SPeter Zijlstra #endif 56452cddbfSPeter Zijlstra 575517d500SChristophe Leroy #define ARCH_DEFINE_STATIC_CALL_RET0_TRAMP(name) \ 585517d500SChristophe Leroy ARCH_DEFINE_STATIC_CALL_TRAMP(name, __static_call_return0) 5973f44fe1SJosh Poimboeuf 6073f44fe1SJosh Poimboeuf #define ARCH_ADD_TRAMP_KEY(name) \ 6173f44fe1SJosh Poimboeuf asm(".pushsection .static_call_tramp_key, \"a\" \n" \ 6273f44fe1SJosh Poimboeuf ".long " STATIC_CALL_TRAMP_STR(name) " - . \n" \ 6373f44fe1SJosh Poimboeuf ".long " STATIC_CALL_KEY_STR(name) " - . \n" \ 6473f44fe1SJosh Poimboeuf ".popsection \n") 6573f44fe1SJosh Poimboeuf 66ee88d363SPeter Zijlstra extern bool __static_call_fixup(void *tramp, u8 op, void *dest); 67ee88d363SPeter Zijlstra 68e6d6c071SJosh Poimboeuf #endif /* _ASM_STATIC_CALL_H */ 69