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