162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright IBM Corp. 2008, 2009 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/linkage.h> 862306a36Sopenharmony_ci#include <asm/asm-offsets.h> 962306a36Sopenharmony_ci#include <asm/ftrace.h> 1062306a36Sopenharmony_ci#include <asm/nospec-insn.h> 1162306a36Sopenharmony_ci#include <asm/ptrace.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define STACK_FRAME_SIZE_PTREGS (STACK_FRAME_OVERHEAD + __PT_SIZE) 1462306a36Sopenharmony_ci#define STACK_PTREGS (STACK_FRAME_OVERHEAD) 1562306a36Sopenharmony_ci#define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS) 1662306a36Sopenharmony_ci#define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW) 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define STACK_FRAME_SIZE_FREGS (STACK_FRAME_OVERHEAD + __FTRACE_REGS_SIZE) 1962306a36Sopenharmony_ci#define STACK_FREGS (STACK_FRAME_OVERHEAD) 2062306a36Sopenharmony_ci#define STACK_FREGS_PTREGS (STACK_FRAME_OVERHEAD + __FTRACE_REGS_PT_REGS) 2162306a36Sopenharmony_ci#define STACK_FREGS_PTREGS_GPRS (STACK_FREGS_PTREGS + __PT_GPRS) 2262306a36Sopenharmony_ci#define STACK_FREGS_PTREGS_PSW (STACK_FREGS_PTREGS + __PT_PSW) 2362306a36Sopenharmony_ci#define STACK_FREGS_PTREGS_ORIG_GPR2 (STACK_FREGS_PTREGS + __PT_ORIG_GPR2) 2462306a36Sopenharmony_ci#define STACK_FREGS_PTREGS_FLAGS (STACK_FREGS_PTREGS + __PT_FLAGS) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* packed stack: allocate just enough for r14, r15 and backchain */ 2762306a36Sopenharmony_ci#define TRACED_FUNC_FRAME_SIZE 24 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#ifdef CONFIG_FUNCTION_TRACER 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci GEN_BR_THUNK %r1 3262306a36Sopenharmony_ci GEN_BR_THUNK %r14 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci .section .kprobes.text, "ax" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciSYM_FUNC_START(ftrace_stub) 3762306a36Sopenharmony_ci BR_EX %r14 3862306a36Sopenharmony_ciSYM_FUNC_END(ftrace_stub) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciSYM_CODE_START(ftrace_stub_direct_tramp) 4162306a36Sopenharmony_ci lgr %r1, %r0 4262306a36Sopenharmony_ci BR_EX %r1 4362306a36Sopenharmony_ciSYM_CODE_END(ftrace_stub_direct_tramp) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci .macro ftrace_regs_entry, allregs=0 4662306a36Sopenharmony_ci stg %r14,(__SF_GPRS+8*8)(%r15) # save traced function caller 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci .if \allregs == 1 4962306a36Sopenharmony_ci # save psw mask 5062306a36Sopenharmony_ci # don't put any instructions clobbering CC before this point 5162306a36Sopenharmony_ci epsw %r1,%r14 5262306a36Sopenharmony_ci risbg %r14,%r1,0,31,32 5362306a36Sopenharmony_ci .endif 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci lgr %r1,%r15 5662306a36Sopenharmony_ci # allocate stack frame for ftrace_caller to contain traced function 5762306a36Sopenharmony_ci aghi %r15,-TRACED_FUNC_FRAME_SIZE 5862306a36Sopenharmony_ci stg %r1,__SF_BACKCHAIN(%r15) 5962306a36Sopenharmony_ci stg %r0,(__SF_GPRS+8*8)(%r15) 6062306a36Sopenharmony_ci stg %r15,(__SF_GPRS+9*8)(%r15) 6162306a36Sopenharmony_ci # allocate ftrace_regs and stack frame for ftrace_trace_function 6262306a36Sopenharmony_ci aghi %r15,-STACK_FRAME_SIZE_FREGS 6362306a36Sopenharmony_ci stg %r1,(STACK_FREGS_PTREGS_GPRS+15*8)(%r15) 6462306a36Sopenharmony_ci xc STACK_FREGS_PTREGS_ORIG_GPR2(8,%r15),STACK_FREGS_PTREGS_ORIG_GPR2(%r15) 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci .if \allregs == 1 6762306a36Sopenharmony_ci stg %r14,(STACK_FREGS_PTREGS_PSW)(%r15) 6862306a36Sopenharmony_ci mvghi STACK_FREGS_PTREGS_FLAGS(%r15),_PIF_FTRACE_FULL_REGS 6962306a36Sopenharmony_ci .else 7062306a36Sopenharmony_ci xc STACK_FREGS_PTREGS_FLAGS(8,%r15),STACK_FREGS_PTREGS_FLAGS(%r15) 7162306a36Sopenharmony_ci .endif 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci lg %r14,(__SF_GPRS+8*8)(%r1) # restore original return address 7462306a36Sopenharmony_ci aghi %r1,-TRACED_FUNC_FRAME_SIZE 7562306a36Sopenharmony_ci stg %r1,__SF_BACKCHAIN(%r15) 7662306a36Sopenharmony_ci stg %r0,(STACK_FREGS_PTREGS_PSW+8)(%r15) 7762306a36Sopenharmony_ci stmg %r2,%r14,(STACK_FREGS_PTREGS_GPRS+2*8)(%r15) 7862306a36Sopenharmony_ci .endm 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciSYM_CODE_START(ftrace_regs_caller) 8162306a36Sopenharmony_ci ftrace_regs_entry 1 8262306a36Sopenharmony_ci j ftrace_common 8362306a36Sopenharmony_ciSYM_CODE_END(ftrace_regs_caller) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ciSYM_CODE_START(ftrace_caller) 8662306a36Sopenharmony_ci ftrace_regs_entry 0 8762306a36Sopenharmony_ci j ftrace_common 8862306a36Sopenharmony_ciSYM_CODE_END(ftrace_caller) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciSYM_CODE_START(ftrace_common) 9162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES 9262306a36Sopenharmony_ci aghik %r2,%r0,-MCOUNT_INSN_SIZE 9362306a36Sopenharmony_ci lgrl %r4,function_trace_op 9462306a36Sopenharmony_ci lgrl %r1,ftrace_func 9562306a36Sopenharmony_ci#else 9662306a36Sopenharmony_ci lgr %r2,%r0 9762306a36Sopenharmony_ci aghi %r2,-MCOUNT_INSN_SIZE 9862306a36Sopenharmony_ci larl %r4,function_trace_op 9962306a36Sopenharmony_ci lg %r4,0(%r4) 10062306a36Sopenharmony_ci larl %r1,ftrace_func 10162306a36Sopenharmony_ci lg %r1,0(%r1) 10262306a36Sopenharmony_ci#endif 10362306a36Sopenharmony_ci lgr %r3,%r14 10462306a36Sopenharmony_ci la %r5,STACK_FREGS(%r15) 10562306a36Sopenharmony_ci BASR_EX %r14,%r1 10662306a36Sopenharmony_ci#ifdef CONFIG_FUNCTION_GRAPH_TRACER 10762306a36Sopenharmony_ci# The j instruction gets runtime patched to a nop instruction. 10862306a36Sopenharmony_ci# See ftrace_enable_ftrace_graph_caller. 10962306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_graph_caller, SYM_L_GLOBAL) 11062306a36Sopenharmony_ci j .Lftrace_graph_caller_end 11162306a36Sopenharmony_ci lmg %r2,%r3,(STACK_FREGS_PTREGS_GPRS+14*8)(%r15) 11262306a36Sopenharmony_ci lg %r4,(STACK_FREGS_PTREGS_PSW+8)(%r15) 11362306a36Sopenharmony_ci brasl %r14,prepare_ftrace_return 11462306a36Sopenharmony_ci stg %r2,(STACK_FREGS_PTREGS_GPRS+14*8)(%r15) 11562306a36Sopenharmony_ci.Lftrace_graph_caller_end: 11662306a36Sopenharmony_ci#endif 11762306a36Sopenharmony_ci lg %r0,(STACK_FREGS_PTREGS_PSW+8)(%r15) 11862306a36Sopenharmony_ci#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES 11962306a36Sopenharmony_ci ltg %r1,STACK_FREGS_PTREGS_ORIG_GPR2(%r15) 12062306a36Sopenharmony_ci locgrz %r1,%r0 12162306a36Sopenharmony_ci#else 12262306a36Sopenharmony_ci lg %r1,STACK_FREGS_PTREGS_ORIG_GPR2(%r15) 12362306a36Sopenharmony_ci ltgr %r1,%r1 12462306a36Sopenharmony_ci jnz 0f 12562306a36Sopenharmony_ci lgr %r1,%r0 12662306a36Sopenharmony_ci#endif 12762306a36Sopenharmony_ci0: lmg %r2,%r15,(STACK_FREGS_PTREGS_GPRS+2*8)(%r15) 12862306a36Sopenharmony_ci BR_EX %r1 12962306a36Sopenharmony_ciSYM_CODE_END(ftrace_common) 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#ifdef CONFIG_FUNCTION_GRAPH_TRACER 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciSYM_FUNC_START(return_to_handler) 13462306a36Sopenharmony_ci stmg %r2,%r5,32(%r15) 13562306a36Sopenharmony_ci lgr %r1,%r15 13662306a36Sopenharmony_ci aghi %r15,-(STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE) 13762306a36Sopenharmony_ci stg %r1,__SF_BACKCHAIN(%r15) 13862306a36Sopenharmony_ci la %r3,STACK_FRAME_OVERHEAD(%r15) 13962306a36Sopenharmony_ci stg %r1,__FGRAPH_RET_FP(%r3) 14062306a36Sopenharmony_ci stg %r2,__FGRAPH_RET_GPR2(%r3) 14162306a36Sopenharmony_ci lgr %r2,%r3 14262306a36Sopenharmony_ci brasl %r14,ftrace_return_to_handler 14362306a36Sopenharmony_ci aghi %r15,STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE 14462306a36Sopenharmony_ci lgr %r14,%r2 14562306a36Sopenharmony_ci lmg %r2,%r5,32(%r15) 14662306a36Sopenharmony_ci BR_EX %r14 14762306a36Sopenharmony_ciSYM_FUNC_END(return_to_handler) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#endif 15062306a36Sopenharmony_ci#endif /* CONFIG_FUNCTION_TRACER */ 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciSYM_CODE_START(ftrace_shared_hotpatch_trampoline_br) 15362306a36Sopenharmony_ci lmg %r0,%r1,2(%r1) 15462306a36Sopenharmony_ci br %r1 15562306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_shared_hotpatch_trampoline_br_end, SYM_L_GLOBAL) 15662306a36Sopenharmony_ciSYM_CODE_END(ftrace_shared_hotpatch_trampoline_br) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#ifdef CONFIG_EXPOLINE 15962306a36Sopenharmony_ciSYM_CODE_START(ftrace_shared_hotpatch_trampoline_exrl) 16062306a36Sopenharmony_ci lmg %r0,%r1,2(%r1) 16162306a36Sopenharmony_ci exrl %r0,0f 16262306a36Sopenharmony_ci j . 16362306a36Sopenharmony_ci0: br %r1 16462306a36Sopenharmony_ciSYM_INNER_LABEL(ftrace_shared_hotpatch_trampoline_exrl_end, SYM_L_GLOBAL) 16562306a36Sopenharmony_ciSYM_CODE_END(ftrace_shared_hotpatch_trampoline_exrl) 16662306a36Sopenharmony_ci#endif /* CONFIG_EXPOLINE */ 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#ifdef CONFIG_RETHOOK 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ciSYM_CODE_START(arch_rethook_trampoline) 17162306a36Sopenharmony_ci stg %r14,(__SF_GPRS+8*8)(%r15) 17262306a36Sopenharmony_ci lay %r15,-STACK_FRAME_SIZE_PTREGS(%r15) 17362306a36Sopenharmony_ci stmg %r0,%r14,STACK_PTREGS_GPRS(%r15) 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci # store original stack pointer in backchain and pt_regs 17662306a36Sopenharmony_ci lay %r7,STACK_FRAME_SIZE_PTREGS(%r15) 17762306a36Sopenharmony_ci stg %r7,__SF_BACKCHAIN(%r15) 17862306a36Sopenharmony_ci stg %r7,STACK_PTREGS_GPRS+(15*8)(%r15) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci # store full psw 18162306a36Sopenharmony_ci epsw %r2,%r3 18262306a36Sopenharmony_ci risbg %r3,%r2,0,31,32 18362306a36Sopenharmony_ci stg %r3,STACK_PTREGS_PSW(%r15) 18462306a36Sopenharmony_ci larl %r1,arch_rethook_trampoline 18562306a36Sopenharmony_ci stg %r1,STACK_PTREGS_PSW+8(%r15) 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci lay %r2,STACK_PTREGS(%r15) 18862306a36Sopenharmony_ci brasl %r14,arch_rethook_trampoline_callback 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci mvc __SF_EMPTY(16,%r7),STACK_PTREGS_PSW(%r15) 19162306a36Sopenharmony_ci lmg %r0,%r15,STACK_PTREGS_GPRS(%r15) 19262306a36Sopenharmony_ci lpswe __SF_EMPTY(%r15) 19362306a36Sopenharmony_ciSYM_CODE_END(arch_rethook_trampoline) 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#endif /* CONFIG_RETHOOK */ 196