1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 2819e50e2SAKASHI Takahiro/* 3819e50e2SAKASHI Takahiro * arch/arm64/kernel/entry-ftrace.S 4819e50e2SAKASHI Takahiro * 5819e50e2SAKASHI Takahiro * Copyright (C) 2013 Linaro Limited 6819e50e2SAKASHI Takahiro * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> 7819e50e2SAKASHI Takahiro */ 8819e50e2SAKASHI Takahiro 9819e50e2SAKASHI Takahiro#include <linux/linkage.h> 10883bbbffSPeter Zijlstra#include <linux/cfi_types.h> 113b23e499STorsten Duwe#include <asm/asm-offsets.h> 12f705d954SArnd Bergmann#include <asm/assembler.h> 13819e50e2SAKASHI Takahiro#include <asm/ftrace.h> 14819e50e2SAKASHI Takahiro#include <asm/insn.h> 15819e50e2SAKASHI Takahiro 1626299b3fSMark Rutland#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS 173b23e499STorsten Duwe/* 183b23e499STorsten Duwe * Due to -fpatchable-function-entry=2, the compiler has placed two NOPs before 193b23e499STorsten Duwe * the regular function prologue. For an enabled callsite, ftrace_init_nop() and 203b23e499STorsten Duwe * ftrace_make_call() have patched those NOPs to: 213b23e499STorsten Duwe * 223b23e499STorsten Duwe * MOV X9, LR 2326299b3fSMark Rutland * BL ftrace_caller 243b23e499STorsten Duwe * 25258c3d62SWill Deacon * Each instrumented function follows the AAPCS, so here x0-x8 and x18-x30 are 26258c3d62SWill Deacon * live (x18 holds the Shadow Call Stack pointer), and x9-x17 are safe to 27258c3d62SWill Deacon * clobber. 283b23e499STorsten Duwe * 2926299b3fSMark Rutland * We save the callsite's context into a struct ftrace_regs before invoking any 3026299b3fSMark Rutland * ftrace callbacks. So that we can get a sensible backtrace, we create frame 3126299b3fSMark Rutland * records for the callsite and the ftrace entry assembly. This is not 3226299b3fSMark Rutland * sufficient for reliable stacktrace: until we create the callsite stack 3326299b3fSMark Rutland * record, its caller is missing from the LR and existing chain of frame 3426299b3fSMark Rutland * records. 353b23e499STorsten Duwe */ 36e434b08bSMark BrownSYM_CODE_START(ftrace_caller) 37742a15b1SMark Brown bti c 383b23e499STorsten Duwe 39*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS 40*2aa6ac03SFlorent Revest /* 41*2aa6ac03SFlorent Revest * The literal pointer to the ops is at an 8-byte aligned boundary 42*2aa6ac03SFlorent Revest * which is either 12 or 16 bytes before the BL instruction in the call 43*2aa6ac03SFlorent Revest * site. See ftrace_call_adjust() for details. 44*2aa6ac03SFlorent Revest * 45*2aa6ac03SFlorent Revest * Therefore here the LR points at `literal + 16` or `literal + 20`, 46*2aa6ac03SFlorent Revest * and we can find the address of the literal in either case by 47*2aa6ac03SFlorent Revest * aligning to an 8-byte boundary and subtracting 16. We do the 48*2aa6ac03SFlorent Revest * alignment first as this allows us to fold the subtraction into the 49*2aa6ac03SFlorent Revest * LDR. 50*2aa6ac03SFlorent Revest */ 51*2aa6ac03SFlorent Revest bic x11, x30, 0x7 52*2aa6ac03SFlorent Revest ldr x11, [x11, #-(4 * AARCH64_INSN_SIZE)] // op 53*2aa6ac03SFlorent Revest 54*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 55*2aa6ac03SFlorent Revest /* 56*2aa6ac03SFlorent Revest * If the op has a direct call, handle it immediately without 57*2aa6ac03SFlorent Revest * saving/restoring registers. 58*2aa6ac03SFlorent Revest */ 59*2aa6ac03SFlorent Revest ldr x17, [x11, #FTRACE_OPS_DIRECT_CALL] // op->direct_call 60*2aa6ac03SFlorent Revest cbnz x17, ftrace_caller_direct 61*2aa6ac03SFlorent Revest#endif 62*2aa6ac03SFlorent Revest#endif 63*2aa6ac03SFlorent Revest 6426299b3fSMark Rutland /* Save original SP */ 6526299b3fSMark Rutland mov x10, sp 6626299b3fSMark Rutland 6726299b3fSMark Rutland /* Make room for ftrace regs, plus two frame records */ 6826299b3fSMark Rutland sub sp, sp, #(FREGS_SIZE + 32) 6926299b3fSMark Rutland 7026299b3fSMark Rutland /* Save function arguments */ 7126299b3fSMark Rutland stp x0, x1, [sp, #FREGS_X0] 7226299b3fSMark Rutland stp x2, x3, [sp, #FREGS_X2] 7326299b3fSMark Rutland stp x4, x5, [sp, #FREGS_X4] 7426299b3fSMark Rutland stp x6, x7, [sp, #FREGS_X6] 7526299b3fSMark Rutland str x8, [sp, #FREGS_X8] 7626299b3fSMark Rutland 77*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 78*2aa6ac03SFlorent Revest str xzr, [sp, #FREGS_DIRECT_TRAMP] 79*2aa6ac03SFlorent Revest#endif 80*2aa6ac03SFlorent Revest 8126299b3fSMark Rutland /* Save the callsite's FP, LR, SP */ 8226299b3fSMark Rutland str x29, [sp, #FREGS_FP] 8326299b3fSMark Rutland str x9, [sp, #FREGS_LR] 8426299b3fSMark Rutland str x10, [sp, #FREGS_SP] 8526299b3fSMark Rutland 8626299b3fSMark Rutland /* Save the PC after the ftrace callsite */ 8726299b3fSMark Rutland str x30, [sp, #FREGS_PC] 8826299b3fSMark Rutland 8926299b3fSMark Rutland /* Create a frame record for the callsite above the ftrace regs */ 9026299b3fSMark Rutland stp x29, x9, [sp, #FREGS_SIZE + 16] 9126299b3fSMark Rutland add x29, sp, #FREGS_SIZE + 16 9226299b3fSMark Rutland 9326299b3fSMark Rutland /* Create our frame record above the ftrace regs */ 9426299b3fSMark Rutland stp x29, x30, [sp, #FREGS_SIZE] 9526299b3fSMark Rutland add x29, sp, #FREGS_SIZE 9626299b3fSMark Rutland 97baaf553dSMark Rutland /* Prepare arguments for the the tracer func */ 983b23e499STorsten Duwe sub x0, x30, #AARCH64_INSN_SIZE // ip (callsite's BL insn) 993b23e499STorsten Duwe mov x1, x9 // parent_ip (callsite's LR) 1003b23e499STorsten Duwe mov x3, sp // regs 1013b23e499STorsten Duwe 102baaf553dSMark Rutland#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS 103*2aa6ac03SFlorent Revest mov x2, x11 // op 104baaf553dSMark Rutland ldr x4, [x2, #FTRACE_OPS_FUNC] // op->func 105baaf553dSMark Rutland blr x4 // op->func(ip, parent_ip, op, regs) 106baaf553dSMark Rutland 107baaf553dSMark Rutland#else 108baaf553dSMark Rutland ldr_l x2, function_trace_op // op 109baaf553dSMark Rutland 110e2d591d2SMark BrownSYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) 111baaf553dSMark Rutland bl ftrace_stub // func(ip, parent_ip, op, regs) 112baaf553dSMark Rutland#endif 1133b23e499STorsten Duwe 1143b23e499STorsten Duwe/* 1153b23e499STorsten Duwe * At the callsite x0-x8 and x19-x30 were live. Any C code will have preserved 1163b23e499STorsten Duwe * x19-x29 per the AAPCS, and we created frame records upon entry, so we need 1173b23e499STorsten Duwe * to restore x0-x8, x29, and x30. 1183b23e499STorsten Duwe */ 1193b23e499STorsten Duwe /* Restore function arguments */ 12026299b3fSMark Rutland ldp x0, x1, [sp, #FREGS_X0] 12126299b3fSMark Rutland ldp x2, x3, [sp, #FREGS_X2] 12226299b3fSMark Rutland ldp x4, x5, [sp, #FREGS_X4] 12326299b3fSMark Rutland ldp x6, x7, [sp, #FREGS_X6] 12426299b3fSMark Rutland ldr x8, [sp, #FREGS_X8] 1253b23e499STorsten Duwe 126*2aa6ac03SFlorent Revest /* Restore the callsite's FP */ 12726299b3fSMark Rutland ldr x29, [sp, #FREGS_FP] 128*2aa6ac03SFlorent Revest 129*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 130*2aa6ac03SFlorent Revest ldr x17, [sp, #FREGS_DIRECT_TRAMP] 131*2aa6ac03SFlorent Revest cbnz x17, ftrace_caller_direct_late 132*2aa6ac03SFlorent Revest#endif 133*2aa6ac03SFlorent Revest 134*2aa6ac03SFlorent Revest /* Restore the callsite's LR and PC */ 13526299b3fSMark Rutland ldr x30, [sp, #FREGS_LR] 13626299b3fSMark Rutland ldr x9, [sp, #FREGS_PC] 1373b23e499STorsten Duwe 1383b23e499STorsten Duwe /* Restore the callsite's SP */ 13926299b3fSMark Rutland add sp, sp, #FREGS_SIZE + 32 1403b23e499STorsten Duwe 1413b23e499STorsten Duwe ret x9 142*2aa6ac03SFlorent Revest 143*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 144*2aa6ac03SFlorent RevestSYM_INNER_LABEL(ftrace_caller_direct_late, SYM_L_LOCAL) 145*2aa6ac03SFlorent Revest /* 146*2aa6ac03SFlorent Revest * Head to a direct trampoline in x17 after having run other tracers. 147*2aa6ac03SFlorent Revest * The ftrace_regs are live, and x0-x8 and FP have been restored. The 148*2aa6ac03SFlorent Revest * LR, PC, and SP have not been restored. 149*2aa6ac03SFlorent Revest */ 150*2aa6ac03SFlorent Revest 151*2aa6ac03SFlorent Revest /* 152*2aa6ac03SFlorent Revest * Restore the callsite's LR and PC matching the trampoline calling 153*2aa6ac03SFlorent Revest * convention. 154*2aa6ac03SFlorent Revest */ 155*2aa6ac03SFlorent Revest ldr x9, [sp, #FREGS_LR] 156*2aa6ac03SFlorent Revest ldr x30, [sp, #FREGS_PC] 157*2aa6ac03SFlorent Revest 158*2aa6ac03SFlorent Revest /* Restore the callsite's SP */ 159*2aa6ac03SFlorent Revest add sp, sp, #FREGS_SIZE + 32 160*2aa6ac03SFlorent Revest 161*2aa6ac03SFlorent RevestSYM_INNER_LABEL(ftrace_caller_direct, SYM_L_LOCAL) 162*2aa6ac03SFlorent Revest /* 163*2aa6ac03SFlorent Revest * Head to a direct trampoline in x17. 164*2aa6ac03SFlorent Revest * 165*2aa6ac03SFlorent Revest * We use `BR X17` as this can safely land on a `BTI C` or `PACIASP` in 166*2aa6ac03SFlorent Revest * the trampoline, and will not unbalance any return stack. 167*2aa6ac03SFlorent Revest */ 168*2aa6ac03SFlorent Revest br x17 169*2aa6ac03SFlorent Revest#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ 17026299b3fSMark RutlandSYM_CODE_END(ftrace_caller) 1713b23e499STorsten Duwe 172*2aa6ac03SFlorent Revest#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS 173*2aa6ac03SFlorent RevestSYM_CODE_START(ftrace_stub_direct_tramp) 174*2aa6ac03SFlorent Revest bti c 175*2aa6ac03SFlorent Revest mov x10, x30 176*2aa6ac03SFlorent Revest mov x30, x9 177*2aa6ac03SFlorent Revest ret x10 178*2aa6ac03SFlorent RevestSYM_CODE_END(ftrace_stub_direct_tramp) 179*2aa6ac03SFlorent Revest#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ 180*2aa6ac03SFlorent Revest 18126299b3fSMark Rutland#else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 1823b23e499STorsten Duwe 183819e50e2SAKASHI Takahiro/* 184819e50e2SAKASHI Takahiro * Gcc with -pg will put the following code in the beginning of each function: 185819e50e2SAKASHI Takahiro * mov x0, x30 186819e50e2SAKASHI Takahiro * bl _mcount 187819e50e2SAKASHI Takahiro * [function's body ...] 188819e50e2SAKASHI Takahiro * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic 189819e50e2SAKASHI Takahiro * ftrace is enabled. 190819e50e2SAKASHI Takahiro * 191819e50e2SAKASHI Takahiro * Please note that x0 as an argument will not be used here because we can 192819e50e2SAKASHI Takahiro * get lr(x30) of instrumented function at any time by winding up call stack 193819e50e2SAKASHI Takahiro * as long as the kernel is compiled without -fomit-frame-pointer. 194819e50e2SAKASHI Takahiro * (or CONFIG_FRAME_POINTER, this is forced on arm64) 195819e50e2SAKASHI Takahiro * 196819e50e2SAKASHI Takahiro * stack layout after mcount_enter in _mcount(): 197819e50e2SAKASHI Takahiro * 198819e50e2SAKASHI Takahiro * current sp/fp => 0:+-----+ 199819e50e2SAKASHI Takahiro * in _mcount() | x29 | -> instrumented function's fp 200819e50e2SAKASHI Takahiro * +-----+ 201819e50e2SAKASHI Takahiro * | x30 | -> _mcount()'s lr (= instrumented function's pc) 202819e50e2SAKASHI Takahiro * old sp => +16:+-----+ 203819e50e2SAKASHI Takahiro * when instrumented | | 204819e50e2SAKASHI Takahiro * function calls | ... | 205819e50e2SAKASHI Takahiro * _mcount() | | 206819e50e2SAKASHI Takahiro * | | 207819e50e2SAKASHI Takahiro * instrumented => +xx:+-----+ 208819e50e2SAKASHI Takahiro * function's fp | x29 | -> parent's fp 209819e50e2SAKASHI Takahiro * +-----+ 210819e50e2SAKASHI Takahiro * | x30 | -> instrumented function's lr (= parent's pc) 211819e50e2SAKASHI Takahiro * +-----+ 212819e50e2SAKASHI Takahiro * | ... | 213819e50e2SAKASHI Takahiro */ 214819e50e2SAKASHI Takahiro 215819e50e2SAKASHI Takahiro .macro mcount_enter 216819e50e2SAKASHI Takahiro stp x29, x30, [sp, #-16]! 217819e50e2SAKASHI Takahiro mov x29, sp 218819e50e2SAKASHI Takahiro .endm 219819e50e2SAKASHI Takahiro 220819e50e2SAKASHI Takahiro .macro mcount_exit 221819e50e2SAKASHI Takahiro ldp x29, x30, [sp], #16 222819e50e2SAKASHI Takahiro ret 223819e50e2SAKASHI Takahiro .endm 224819e50e2SAKASHI Takahiro 225819e50e2SAKASHI Takahiro .macro mcount_adjust_addr rd, rn 226819e50e2SAKASHI Takahiro sub \rd, \rn, #AARCH64_INSN_SIZE 227819e50e2SAKASHI Takahiro .endm 228819e50e2SAKASHI Takahiro 229819e50e2SAKASHI Takahiro /* for instrumented function's parent */ 230819e50e2SAKASHI Takahiro .macro mcount_get_parent_fp reg 231819e50e2SAKASHI Takahiro ldr \reg, [x29] 232819e50e2SAKASHI Takahiro ldr \reg, [\reg] 233819e50e2SAKASHI Takahiro .endm 234819e50e2SAKASHI Takahiro 235819e50e2SAKASHI Takahiro /* for instrumented function */ 236819e50e2SAKASHI Takahiro .macro mcount_get_pc0 reg 237819e50e2SAKASHI Takahiro mcount_adjust_addr \reg, x30 238819e50e2SAKASHI Takahiro .endm 239819e50e2SAKASHI Takahiro 240819e50e2SAKASHI Takahiro .macro mcount_get_pc reg 241819e50e2SAKASHI Takahiro ldr \reg, [x29, #8] 242819e50e2SAKASHI Takahiro mcount_adjust_addr \reg, \reg 243819e50e2SAKASHI Takahiro .endm 244819e50e2SAKASHI Takahiro 245819e50e2SAKASHI Takahiro .macro mcount_get_lr reg 246819e50e2SAKASHI Takahiro ldr \reg, [x29] 247819e50e2SAKASHI Takahiro ldr \reg, [\reg, #8] 248819e50e2SAKASHI Takahiro .endm 249819e50e2SAKASHI Takahiro 250819e50e2SAKASHI Takahiro .macro mcount_get_lr_addr reg 251819e50e2SAKASHI Takahiro ldr \reg, [x29] 252819e50e2SAKASHI Takahiro add \reg, \reg, #8 253819e50e2SAKASHI Takahiro .endm 254819e50e2SAKASHI Takahiro 255bd7d38dbSAKASHI Takahiro/* 256bd7d38dbSAKASHI Takahiro * _mcount() is used to build the kernel with -pg option, but all the branch 257bd7d38dbSAKASHI Takahiro * instructions to _mcount() are replaced to NOP initially at kernel start up, 258bd7d38dbSAKASHI Takahiro * and later on, NOP to branch to ftrace_caller() when enabled or branch to 259bd7d38dbSAKASHI Takahiro * NOP when disabled per-function base. 260bd7d38dbSAKASHI Takahiro */ 261e2d591d2SMark BrownSYM_FUNC_START(_mcount) 262bd7d38dbSAKASHI Takahiro ret 263e2d591d2SMark BrownSYM_FUNC_END(_mcount) 264dbd31962SMark RutlandEXPORT_SYMBOL(_mcount) 265dbd31962SMark RutlandNOKPROBE(_mcount) 266bd7d38dbSAKASHI Takahiro 267bd7d38dbSAKASHI Takahiro/* 268bd7d38dbSAKASHI Takahiro * void ftrace_caller(unsigned long return_address) 269bd7d38dbSAKASHI Takahiro * @return_address: return address to instrumented function 270bd7d38dbSAKASHI Takahiro * 271bd7d38dbSAKASHI Takahiro * This function is a counterpart of _mcount() in 'static' ftrace, and 272bd7d38dbSAKASHI Takahiro * makes calls to: 273bd7d38dbSAKASHI Takahiro * - tracer function to probe instrumented function's entry, 274bd7d38dbSAKASHI Takahiro * - ftrace_graph_caller to set up an exit hook 275bd7d38dbSAKASHI Takahiro */ 276e2d591d2SMark BrownSYM_FUNC_START(ftrace_caller) 277bd7d38dbSAKASHI Takahiro mcount_enter 278bd7d38dbSAKASHI Takahiro 279bd7d38dbSAKASHI Takahiro mcount_get_pc0 x0 // function's pc 280bd7d38dbSAKASHI Takahiro mcount_get_lr x1 // function's lr 281bd7d38dbSAKASHI Takahiro 282e2d591d2SMark BrownSYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) // tracer(pc, lr); 283bd7d38dbSAKASHI Takahiro nop // This will be replaced with "bl xxx" 284bd7d38dbSAKASHI Takahiro // where xxx can be any kind of tracer. 285bd7d38dbSAKASHI Takahiro 286bd7d38dbSAKASHI Takahiro#ifdef CONFIG_FUNCTION_GRAPH_TRACER 28769d113b5SKunihiko HayashiSYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) // ftrace_graph_caller(); 288bd7d38dbSAKASHI Takahiro nop // If enabled, this will be replaced 289bd7d38dbSAKASHI Takahiro // "b ftrace_graph_caller" 290bd7d38dbSAKASHI Takahiro#endif 291bd7d38dbSAKASHI Takahiro 292bd7d38dbSAKASHI Takahiro mcount_exit 293e2d591d2SMark BrownSYM_FUNC_END(ftrace_caller) 294819e50e2SAKASHI Takahiro 295819e50e2SAKASHI Takahiro#ifdef CONFIG_FUNCTION_GRAPH_TRACER 296819e50e2SAKASHI Takahiro/* 297819e50e2SAKASHI Takahiro * void ftrace_graph_caller(void) 298819e50e2SAKASHI Takahiro * 299819e50e2SAKASHI Takahiro * Called from _mcount() or ftrace_caller() when function_graph tracer is 300819e50e2SAKASHI Takahiro * selected. 301819e50e2SAKASHI Takahiro * This function w/ prepare_ftrace_return() fakes link register's value on 302819e50e2SAKASHI Takahiro * the call stack in order to intercept instrumented function's return path 303819e50e2SAKASHI Takahiro * and run return_to_handler() later on its exit. 304819e50e2SAKASHI Takahiro */ 305e2d591d2SMark BrownSYM_FUNC_START(ftrace_graph_caller) 3067dc48bf9SMark Rutland mcount_get_pc x0 // function's pc 3077dc48bf9SMark Rutland mcount_get_lr_addr x1 // pointer to function's saved lr 308819e50e2SAKASHI Takahiro mcount_get_parent_fp x2 // parent's fp 3097dc48bf9SMark Rutland bl prepare_ftrace_return // prepare_ftrace_return(pc, &lr, fp) 310819e50e2SAKASHI Takahiro 311819e50e2SAKASHI Takahiro mcount_exit 312e2d591d2SMark BrownSYM_FUNC_END(ftrace_graph_caller) 3133b23e499STorsten Duwe#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 31426299b3fSMark Rutland#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */ 315819e50e2SAKASHI Takahiro 316883bbbffSPeter ZijlstraSYM_TYPED_FUNC_START(ftrace_stub) 3173b23e499STorsten Duwe ret 318e2d591d2SMark BrownSYM_FUNC_END(ftrace_stub) 3193b23e499STorsten Duwe 3202598ac6eSSami Tolvanen#ifdef CONFIG_FUNCTION_GRAPH_TRACER 321883bbbffSPeter ZijlstraSYM_TYPED_FUNC_START(ftrace_stub_graph) 322883bbbffSPeter Zijlstra ret 323883bbbffSPeter ZijlstraSYM_FUNC_END(ftrace_stub_graph) 324883bbbffSPeter Zijlstra 325819e50e2SAKASHI Takahiro/* 326819e50e2SAKASHI Takahiro * void return_to_handler(void) 327819e50e2SAKASHI Takahiro * 328819e50e2SAKASHI Takahiro * Run ftrace_return_to_handler() before going back to parent. 3295c176affSMark Rutland * @fp is checked against the value passed by ftrace_graph_caller(). 330819e50e2SAKASHI Takahiro */ 3311e4729edSMark BrownSYM_CODE_START(return_to_handler) 33249e258e0SMark Rutland /* save return value regs */ 33349e258e0SMark Rutland sub sp, sp, #FGRET_REGS_SIZE 33449e258e0SMark Rutland stp x0, x1, [sp, #FGRET_REGS_X0] 33549e258e0SMark Rutland stp x2, x3, [sp, #FGRET_REGS_X2] 33649e258e0SMark Rutland stp x4, x5, [sp, #FGRET_REGS_X4] 33749e258e0SMark Rutland stp x6, x7, [sp, #FGRET_REGS_X6] 33849e258e0SMark Rutland str x29, [sp, #FGRET_REGS_FP] // parent's fp 339819e50e2SAKASHI Takahiro 340819e50e2SAKASHI Takahiro mov x0, sp 341819e50e2SAKASHI Takahiro bl ftrace_return_to_handler // addr = ftrace_return_to_hander(regs); 34249e258e0SMark Rutland mov x30, x0 // restore the original return address 34349e258e0SMark Rutland 34449e258e0SMark Rutland /* restore return value regs */ 34549e258e0SMark Rutland ldp x0, x1, [sp, #FGRET_REGS_X0] 34649e258e0SMark Rutland ldp x2, x3, [sp, #FGRET_REGS_X2] 34749e258e0SMark Rutland ldp x4, x5, [sp, #FGRET_REGS_X4] 34849e258e0SMark Rutland ldp x6, x7, [sp, #FGRET_REGS_X6] 34949e258e0SMark Rutland add sp, sp, #FGRET_REGS_SIZE 350819e50e2SAKASHI Takahiro 3511e4729edSMark Brown ret 352819e50e2SAKASHI TakahiroSYM_CODE_END(return_to_handler) 353#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 354