162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2014 Steven Rostedt, Red Hat Inc 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/cfi_types.h> 762306a36Sopenharmony_ci#include <linux/linkage.h> 862306a36Sopenharmony_ci#include <asm/asm-offsets.h> 962306a36Sopenharmony_ci#include <asm/ptrace.h> 1062306a36Sopenharmony_ci#include <asm/ftrace.h> 1162306a36Sopenharmony_ci#include <asm/export.h> 1262306a36Sopenharmony_ci#include <asm/nospec-branch.h> 1362306a36Sopenharmony_ci#include <asm/unwind_hints.h> 1462306a36Sopenharmony_ci#include <asm/frame.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci .code64 1762306a36Sopenharmony_ci .section .text, "ax" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#ifdef CONFIG_FRAME_POINTER 2062306a36Sopenharmony_ci/* Save parent and function stack frames (rip and rbp) */ 2162306a36Sopenharmony_ci# define MCOUNT_FRAME_SIZE (8+16*2) 2262306a36Sopenharmony_ci#else 2362306a36Sopenharmony_ci/* No need to save a stack frame */ 2462306a36Sopenharmony_ci# define MCOUNT_FRAME_SIZE 0 2562306a36Sopenharmony_ci#endif /* CONFIG_FRAME_POINTER */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* Size of stack used to save mcount regs in save_mcount_regs */ 2862306a36Sopenharmony_ci#define MCOUNT_REG_SIZE (FRAME_SIZE + MCOUNT_FRAME_SIZE) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * gcc -pg option adds a call to 'mcount' in most functions. 3262306a36Sopenharmony_ci * When -mfentry is used, the call is to 'fentry' and not 'mcount' 3362306a36Sopenharmony_ci * and is done before the function's stack frame is set up. 3462306a36Sopenharmony_ci * They both require a set of regs to be saved before calling 3562306a36Sopenharmony_ci * any C code and restored before returning back to the function. 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * On boot up, all these calls are converted into nops. When tracing 3862306a36Sopenharmony_ci * is enabled, the call can jump to either ftrace_caller or 3962306a36Sopenharmony_ci * ftrace_regs_caller. Callbacks (tracing functions) that require 4062306a36Sopenharmony_ci * ftrace_regs_caller (like kprobes) need to have pt_regs passed to 4162306a36Sopenharmony_ci * it. For this reason, the size of the pt_regs structure will be 4262306a36Sopenharmony_ci * allocated on the stack and the required mcount registers will 4362306a36Sopenharmony_ci * be saved in the locations that pt_regs has them in. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * @added: the amount of stack added before calling this 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * After this is called, the following registers contain: 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * %rdi - holds the address that called the trampoline 5262306a36Sopenharmony_ci * %rsi - holds the parent function (traced function's return address) 5362306a36Sopenharmony_ci * %rdx - holds the original %rbp 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci.macro save_mcount_regs added=0 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#ifdef CONFIG_FRAME_POINTER 5862306a36Sopenharmony_ci /* Save the original rbp */ 5962306a36Sopenharmony_ci pushq %rbp 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci /* 6262306a36Sopenharmony_ci * Stack traces will stop at the ftrace trampoline if the frame pointer 6362306a36Sopenharmony_ci * is not set up properly. If fentry is used, we need to save a frame 6462306a36Sopenharmony_ci * pointer for the parent as well as the function traced, because the 6562306a36Sopenharmony_ci * fentry is called before the stack frame is set up, where as mcount 6662306a36Sopenharmony_ci * is called afterward. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* Save the parent pointer (skip orig rbp and our return address) */ 7062306a36Sopenharmony_ci pushq \added+8*2(%rsp) 7162306a36Sopenharmony_ci pushq %rbp 7262306a36Sopenharmony_ci movq %rsp, %rbp 7362306a36Sopenharmony_ci /* Save the return address (now skip orig rbp, rbp and parent) */ 7462306a36Sopenharmony_ci pushq \added+8*3(%rsp) 7562306a36Sopenharmony_ci pushq %rbp 7662306a36Sopenharmony_ci movq %rsp, %rbp 7762306a36Sopenharmony_ci#endif /* CONFIG_FRAME_POINTER */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* 8062306a36Sopenharmony_ci * We add enough stack to save all regs. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ci subq $(FRAME_SIZE), %rsp 8362306a36Sopenharmony_ci movq %rax, RAX(%rsp) 8462306a36Sopenharmony_ci movq %rcx, RCX(%rsp) 8562306a36Sopenharmony_ci movq %rdx, RDX(%rsp) 8662306a36Sopenharmony_ci movq %rsi, RSI(%rsp) 8762306a36Sopenharmony_ci movq %rdi, RDI(%rsp) 8862306a36Sopenharmony_ci movq %r8, R8(%rsp) 8962306a36Sopenharmony_ci movq %r9, R9(%rsp) 9062306a36Sopenharmony_ci movq $0, ORIG_RAX(%rsp) 9162306a36Sopenharmony_ci /* 9262306a36Sopenharmony_ci * Save the original RBP. Even though the mcount ABI does not 9362306a36Sopenharmony_ci * require this, it helps out callers. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_ci#ifdef CONFIG_FRAME_POINTER 9662306a36Sopenharmony_ci movq MCOUNT_REG_SIZE-8(%rsp), %rdx 9762306a36Sopenharmony_ci#else 9862306a36Sopenharmony_ci movq %rbp, %rdx 9962306a36Sopenharmony_ci#endif 10062306a36Sopenharmony_ci movq %rdx, RBP(%rsp) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* Copy the parent address into %rsi (second parameter) */ 10362306a36Sopenharmony_ci movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Move RIP to its proper location */ 10662306a36Sopenharmony_ci movq MCOUNT_REG_SIZE+\added(%rsp), %rdi 10762306a36Sopenharmony_ci movq %rdi, RIP(%rsp) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* 11062306a36Sopenharmony_ci * Now %rdi (the first parameter) has the return address of 11162306a36Sopenharmony_ci * where ftrace_call returns. But the callbacks expect the 11262306a36Sopenharmony_ci * address of the call itself. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci subq $MCOUNT_INSN_SIZE, %rdi 11562306a36Sopenharmony_ci .endm 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci.macro restore_mcount_regs save=0 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* ftrace_regs_caller or frame pointers require this */ 12062306a36Sopenharmony_ci movq RBP(%rsp), %rbp 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci movq R9(%rsp), %r9 12362306a36Sopenharmony_ci movq R8(%rsp), %r8 12462306a36Sopenharmony_ci movq RDI(%rsp), %rdi 12562306a36Sopenharmony_ci movq RSI(%rsp), %rsi 12662306a36Sopenharmony_ci movq RDX(%rsp), %rdx 12762306a36Sopenharmony_ci movq RCX(%rsp), %rcx 12862306a36Sopenharmony_ci movq RAX(%rsp), %rax 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci addq $MCOUNT_REG_SIZE-\save, %rsp 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci .endm 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ciSYM_TYPED_FUNC_START(ftrace_stub) 13562306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 13662306a36Sopenharmony_ci RET 13762306a36Sopenharmony_ciSYM_FUNC_END(ftrace_stub) 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#ifdef CONFIG_FUNCTION_GRAPH_TRACER 14062306a36Sopenharmony_ciSYM_TYPED_FUNC_START(ftrace_stub_graph) 14162306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 14262306a36Sopenharmony_ci RET 14362306a36Sopenharmony_ciSYM_FUNC_END(ftrace_stub_graph) 14462306a36Sopenharmony_ci#endif 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#ifdef CONFIG_DYNAMIC_FTRACE 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciSYM_FUNC_START(__fentry__) 14962306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 15062306a36Sopenharmony_ci RET 15162306a36Sopenharmony_ciSYM_FUNC_END(__fentry__) 15262306a36Sopenharmony_ciEXPORT_SYMBOL(__fentry__) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciSYM_FUNC_START(ftrace_caller) 15562306a36Sopenharmony_ci /* save_mcount_regs fills in first two parameters */ 15662306a36Sopenharmony_ci save_mcount_regs 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Stack - skipping return address of ftrace_caller */ 16162306a36Sopenharmony_ci leaq MCOUNT_REG_SIZE+8(%rsp), %rcx 16262306a36Sopenharmony_ci movq %rcx, RSP(%rsp) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL) 16562306a36Sopenharmony_ci ANNOTATE_NOENDBR 16662306a36Sopenharmony_ci /* Load the ftrace_ops into the 3rd parameter */ 16762306a36Sopenharmony_ci movq function_trace_op(%rip), %rdx 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* regs go into 4th parameter */ 17062306a36Sopenharmony_ci leaq (%rsp), %rcx 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* Only ops with REGS flag set should have CS register set */ 17362306a36Sopenharmony_ci movq $0, CS(%rsp) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Account for the function call below */ 17662306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 17962306a36Sopenharmony_ci ANNOTATE_NOENDBR 18062306a36Sopenharmony_ci call ftrace_stub 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* Handlers can change the RIP */ 18362306a36Sopenharmony_ci movq RIP(%rsp), %rax 18462306a36Sopenharmony_ci movq %rax, MCOUNT_REG_SIZE(%rsp) 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci restore_mcount_regs 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* 18962306a36Sopenharmony_ci * The code up to this label is copied into trampolines so 19062306a36Sopenharmony_ci * think twice before adding any new code or changing the 19162306a36Sopenharmony_ci * layout here. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_caller_end, SYM_L_GLOBAL) 19462306a36Sopenharmony_ci ANNOTATE_NOENDBR 19562306a36Sopenharmony_ci RET 19662306a36Sopenharmony_ciSYM_FUNC_END(ftrace_caller); 19762306a36Sopenharmony_ciSTACK_FRAME_NON_STANDARD_FP(ftrace_caller) 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ciSYM_FUNC_START(ftrace_regs_caller) 20062306a36Sopenharmony_ci /* Save the current flags before any operations that can change them */ 20162306a36Sopenharmony_ci pushfq 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* added 8 bytes to save flags */ 20462306a36Sopenharmony_ci save_mcount_regs 8 20562306a36Sopenharmony_ci /* save_mcount_regs fills in first two parameters */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL) 21062306a36Sopenharmony_ci ANNOTATE_NOENDBR 21162306a36Sopenharmony_ci /* Load the ftrace_ops into the 3rd parameter */ 21262306a36Sopenharmony_ci movq function_trace_op(%rip), %rdx 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* Save the rest of pt_regs */ 21562306a36Sopenharmony_ci movq %r15, R15(%rsp) 21662306a36Sopenharmony_ci movq %r14, R14(%rsp) 21762306a36Sopenharmony_ci movq %r13, R13(%rsp) 21862306a36Sopenharmony_ci movq %r12, R12(%rsp) 21962306a36Sopenharmony_ci movq %r11, R11(%rsp) 22062306a36Sopenharmony_ci movq %r10, R10(%rsp) 22162306a36Sopenharmony_ci movq %rbx, RBX(%rsp) 22262306a36Sopenharmony_ci /* Copy saved flags */ 22362306a36Sopenharmony_ci movq MCOUNT_REG_SIZE(%rsp), %rcx 22462306a36Sopenharmony_ci movq %rcx, EFLAGS(%rsp) 22562306a36Sopenharmony_ci /* Kernel segments */ 22662306a36Sopenharmony_ci movq $__KERNEL_DS, %rcx 22762306a36Sopenharmony_ci movq %rcx, SS(%rsp) 22862306a36Sopenharmony_ci movq $__KERNEL_CS, %rcx 22962306a36Sopenharmony_ci movq %rcx, CS(%rsp) 23062306a36Sopenharmony_ci /* Stack - skipping return address and flags */ 23162306a36Sopenharmony_ci leaq MCOUNT_REG_SIZE+8*2(%rsp), %rcx 23262306a36Sopenharmony_ci movq %rcx, RSP(%rsp) 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci ENCODE_FRAME_POINTER 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* regs go into 4th parameter */ 23762306a36Sopenharmony_ci leaq (%rsp), %rcx 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Account for the function call below */ 24062306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL) 24362306a36Sopenharmony_ci ANNOTATE_NOENDBR 24462306a36Sopenharmony_ci call ftrace_stub 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Copy flags back to SS, to restore them */ 24762306a36Sopenharmony_ci movq EFLAGS(%rsp), %rax 24862306a36Sopenharmony_ci movq %rax, MCOUNT_REG_SIZE(%rsp) 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Handlers can change the RIP */ 25162306a36Sopenharmony_ci movq RIP(%rsp), %rax 25262306a36Sopenharmony_ci movq %rax, MCOUNT_REG_SIZE+8(%rsp) 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* restore the rest of pt_regs */ 25562306a36Sopenharmony_ci movq R15(%rsp), %r15 25662306a36Sopenharmony_ci movq R14(%rsp), %r14 25762306a36Sopenharmony_ci movq R13(%rsp), %r13 25862306a36Sopenharmony_ci movq R12(%rsp), %r12 25962306a36Sopenharmony_ci movq R10(%rsp), %r10 26062306a36Sopenharmony_ci movq RBX(%rsp), %rbx 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci movq ORIG_RAX(%rsp), %rax 26362306a36Sopenharmony_ci movq %rax, MCOUNT_REG_SIZE-8(%rsp) 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* 26662306a36Sopenharmony_ci * If ORIG_RAX is anything but zero, make this a call to that. 26762306a36Sopenharmony_ci * See arch_ftrace_set_direct_caller(). 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci testq %rax, %rax 27062306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_regs_caller_jmp, SYM_L_GLOBAL) 27162306a36Sopenharmony_ci ANNOTATE_NOENDBR 27262306a36Sopenharmony_ci jnz 1f 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci restore_mcount_regs 27562306a36Sopenharmony_ci /* Restore flags */ 27662306a36Sopenharmony_ci popfq 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* 27962306a36Sopenharmony_ci * The trampoline will add the return. 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL) 28262306a36Sopenharmony_ci ANNOTATE_NOENDBR 28362306a36Sopenharmony_ci RET 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci /* Swap the flags with orig_rax */ 28662306a36Sopenharmony_ci1: movq MCOUNT_REG_SIZE(%rsp), %rdi 28762306a36Sopenharmony_ci movq %rdi, MCOUNT_REG_SIZE-8(%rsp) 28862306a36Sopenharmony_ci movq %rax, MCOUNT_REG_SIZE(%rsp) 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci restore_mcount_regs 8 29162306a36Sopenharmony_ci /* Restore flags */ 29262306a36Sopenharmony_ci popfq 29362306a36Sopenharmony_ci UNWIND_HINT_FUNC 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* 29662306a36Sopenharmony_ci * The above left an extra return value on the stack; effectively 29762306a36Sopenharmony_ci * doing a tail-call without using a register. This PUSH;RET 29862306a36Sopenharmony_ci * pattern unbalances the RSB, inject a pointless CALL to rebalance. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci ANNOTATE_INTRA_FUNCTION_CALL 30162306a36Sopenharmony_ci CALL .Ldo_rebalance 30262306a36Sopenharmony_ci int3 30362306a36Sopenharmony_ci.Ldo_rebalance: 30462306a36Sopenharmony_ci add $8, %rsp 30562306a36Sopenharmony_ci ALTERNATIVE __stringify(RET), \ 30662306a36Sopenharmony_ci __stringify(ANNOTATE_UNRET_SAFE; ret; int3), \ 30762306a36Sopenharmony_ci X86_FEATURE_CALL_DEPTH 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ciSYM_FUNC_END(ftrace_regs_caller) 31062306a36Sopenharmony_ciSTACK_FRAME_NON_STANDARD_FP(ftrace_regs_caller) 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ciSYM_FUNC_START(ftrace_stub_direct_tramp) 31362306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 31462306a36Sopenharmony_ci RET 31562306a36Sopenharmony_ciSYM_FUNC_END(ftrace_stub_direct_tramp) 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci#else /* ! CONFIG_DYNAMIC_FTRACE */ 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ciSYM_FUNC_START(__fentry__) 32062306a36Sopenharmony_ci CALL_DEPTH_ACCOUNT 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci cmpq $ftrace_stub, ftrace_trace_function 32362306a36Sopenharmony_ci jnz trace 32462306a36Sopenharmony_ci RET 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_citrace: 32762306a36Sopenharmony_ci /* save_mcount_regs fills in first two parameters */ 32862306a36Sopenharmony_ci save_mcount_regs 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* 33162306a36Sopenharmony_ci * When DYNAMIC_FTRACE is not defined, ARCH_SUPPORTS_FTRACE_OPS is not 33262306a36Sopenharmony_ci * set (see include/asm/ftrace.h and include/linux/ftrace.h). Only the 33362306a36Sopenharmony_ci * ip and parent ip are used and the list function is called when 33462306a36Sopenharmony_ci * function tracing is enabled. 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci movq ftrace_trace_function, %r8 33762306a36Sopenharmony_ci CALL_NOSPEC r8 33862306a36Sopenharmony_ci restore_mcount_regs 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci jmp ftrace_stub 34162306a36Sopenharmony_ciSYM_FUNC_END(__fentry__) 34262306a36Sopenharmony_ciEXPORT_SYMBOL(__fentry__) 34362306a36Sopenharmony_ciSTACK_FRAME_NON_STANDARD_FP(__fentry__) 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci#endif /* CONFIG_DYNAMIC_FTRACE */ 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci#ifdef CONFIG_FUNCTION_GRAPH_TRACER 34862306a36Sopenharmony_ciSYM_CODE_START(return_to_handler) 34962306a36Sopenharmony_ci UNWIND_HINT_UNDEFINED 35062306a36Sopenharmony_ci ANNOTATE_NOENDBR 35162306a36Sopenharmony_ci subq $24, %rsp 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* Save the return values */ 35462306a36Sopenharmony_ci movq %rax, (%rsp) 35562306a36Sopenharmony_ci movq %rdx, 8(%rsp) 35662306a36Sopenharmony_ci movq %rbp, 16(%rsp) 35762306a36Sopenharmony_ci movq %rsp, %rdi 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci call ftrace_return_to_handler 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci movq %rax, %rdi 36262306a36Sopenharmony_ci movq 8(%rsp), %rdx 36362306a36Sopenharmony_ci movq (%rsp), %rax 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci addq $24, %rsp 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Jump back to the old return address. This cannot be JMP_NOSPEC rdi 36862306a36Sopenharmony_ci * since IBT would demand that contain ENDBR, which simply isn't so for 36962306a36Sopenharmony_ci * return addresses. Use a retpoline here to keep the RSB balanced. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci ANNOTATE_INTRA_FUNCTION_CALL 37262306a36Sopenharmony_ci call .Ldo_rop 37362306a36Sopenharmony_ci int3 37462306a36Sopenharmony_ci.Ldo_rop: 37562306a36Sopenharmony_ci mov %rdi, (%rsp) 37662306a36Sopenharmony_ci ALTERNATIVE __stringify(RET), \ 37762306a36Sopenharmony_ci __stringify(ANNOTATE_UNRET_SAFE; ret; int3), \ 37862306a36Sopenharmony_ci X86_FEATURE_CALL_DEPTH 37962306a36Sopenharmony_ciSYM_CODE_END(return_to_handler) 38062306a36Sopenharmony_ci#endif 381