root/arch/riscv/kernel/mcount.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /* Copyright (C) 2017 Andes Technology Corporation */
   3 
   4 #include <linux/init.h>
   5 #include <linux/linkage.h>
   6 #include <asm/asm.h>
   7 #include <asm/csr.h>
   8 #include <asm/unistd.h>
   9 #include <asm/thread_info.h>
  10 #include <asm/asm-offsets.h>
  11 #include <asm-generic/export.h>
  12 #include <asm/ftrace.h>
  13 
  14         .text
  15 
  16         .macro SAVE_ABI_STATE
  17         addi    sp, sp, -16
  18         sd      s0, 0(sp)
  19         sd      ra, 8(sp)
  20         addi    s0, sp, 16
  21         .endm
  22 
  23         /*
  24          * The call to ftrace_return_to_handler would overwrite the return
  25          * register if a0 was not saved.
  26          */
  27         .macro SAVE_RET_ABI_STATE
  28         addi    sp, sp, -32
  29         sd      s0, 16(sp)
  30         sd      ra, 24(sp)
  31         sd      a0, 8(sp)
  32         addi    s0, sp, 32
  33         .endm
  34 
  35         .macro RESTORE_ABI_STATE
  36         ld      ra, 8(sp)
  37         ld      s0, 0(sp)
  38         addi    sp, sp, 16
  39         .endm
  40 
  41         .macro RESTORE_RET_ABI_STATE
  42         ld      ra, 24(sp)
  43         ld      s0, 16(sp)
  44         ld      a0, 8(sp)
  45         addi    sp, sp, 32
  46         .endm
  47 
  48 ENTRY(ftrace_stub)
  49 #ifdef CONFIG_DYNAMIC_FTRACE
  50        .global _mcount
  51        .set    _mcount, ftrace_stub
  52 #endif
  53         ret
  54 ENDPROC(ftrace_stub)
  55 
  56 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  57 ENTRY(return_to_handler)
  58 /*
  59  * On implementing the frame point test, the ideal way is to compare the
  60  * s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return.
  61  * However, the psABI of variable-length-argument functions does not allow this.
  62  *
  63  * So alternatively we check the *old* frame pointer position, that is, the
  64  * value stored in -16(s0) on entry, and the s0 on return.
  65  */
  66 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
  67         mv      t6, s0
  68 #endif
  69         SAVE_RET_ABI_STATE
  70 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
  71         mv      a0, t6
  72 #endif
  73         call    ftrace_return_to_handler
  74         mv      a1, a0
  75         RESTORE_RET_ABI_STATE
  76         jalr    a1
  77 ENDPROC(return_to_handler)
  78 #endif
  79 
  80 #ifndef CONFIG_DYNAMIC_FTRACE
  81 ENTRY(_mcount)
  82         la      t4, ftrace_stub
  83 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  84         la      t0, ftrace_graph_return
  85         ld      t1, 0(t0)
  86         bne     t1, t4, do_ftrace_graph_caller
  87 
  88         la      t3, ftrace_graph_entry
  89         ld      t2, 0(t3)
  90         la      t6, ftrace_graph_entry_stub
  91         bne     t2, t6, do_ftrace_graph_caller
  92 #endif
  93         la      t3, ftrace_trace_function
  94         ld      t5, 0(t3)
  95         bne     t5, t4, do_trace
  96         ret
  97 
  98 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  99 /*
 100  * A pseudo representation for the function graph tracer:
 101  * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller)
 102  */
 103 do_ftrace_graph_caller:
 104         addi    a0, s0, -8
 105         mv      a1, ra
 106 #ifdef HAVE_FUNCTION_GRAPH_FP_TEST
 107         ld      a2, -16(s0)
 108 #endif
 109         SAVE_ABI_STATE
 110         call    prepare_ftrace_return
 111         RESTORE_ABI_STATE
 112         ret
 113 #endif
 114 
 115 /*
 116  * A pseudo representation for the function tracer:
 117  * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller)
 118  */
 119 do_trace:
 120         ld      a1, -8(s0)
 121         mv      a0, ra
 122 
 123         SAVE_ABI_STATE
 124         jalr    t5
 125         RESTORE_ABI_STATE
 126         ret
 127 ENDPROC(_mcount)
 128 #endif
 129 EXPORT_SYMBOL(_mcount)

/* [<][>][^][v][top][bottom][index][help] */