1 
   2 
   3 
   4 
   5 
   6 #include <linux/linkage.h>
   7 #include <asm/ptrace.h>
   8 #include <asm/ftrace.h>
   9 #include <asm/export.h>
  10 #include <asm/nospec-branch.h>
  11 #include <asm/unwind_hints.h>
  12 #include <asm/frame.h>
  13 
  14         .code64
  15         .section .entry.text, "ax"
  16 
  17 # define function_hook  __fentry__
  18 EXPORT_SYMBOL(__fentry__)
  19 
  20 #ifdef CONFIG_FRAME_POINTER
  21 
  22 #  define MCOUNT_FRAME_SIZE     (8+16*2)
  23 #else
  24 
  25 # define MCOUNT_FRAME_SIZE      0
  26 #endif 
  27 
  28 
  29 #define MCOUNT_REG_SIZE         (SS+8 + MCOUNT_FRAME_SIZE)
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 .macro save_mcount_regs added=0
  57 
  58 #ifdef CONFIG_FRAME_POINTER
  59         
  60         pushq %rbp
  61 
  62         
  63 
  64 
  65 
  66 
  67 
  68 
  69 
  70         
  71         pushq \added+8*2(%rsp)
  72         pushq %rbp
  73         movq %rsp, %rbp
  74         
  75         pushq \added+8*3(%rsp)
  76         pushq %rbp
  77         movq %rsp, %rbp
  78 #endif 
  79 
  80         
  81 
  82 
  83         subq $(MCOUNT_REG_SIZE - MCOUNT_FRAME_SIZE), %rsp
  84         movq %rax, RAX(%rsp)
  85         movq %rcx, RCX(%rsp)
  86         movq %rdx, RDX(%rsp)
  87         movq %rsi, RSI(%rsp)
  88         movq %rdi, RDI(%rsp)
  89         movq %r8, R8(%rsp)
  90         movq %r9, R9(%rsp)
  91         
  92 
  93 
  94 
  95 #ifdef CONFIG_FRAME_POINTER
  96         movq MCOUNT_REG_SIZE-8(%rsp), %rdx
  97 #else
  98         movq %rbp, %rdx
  99 #endif
 100         movq %rdx, RBP(%rsp)
 101 
 102         
 103         movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi
 104 
 105          
 106         movq MCOUNT_REG_SIZE+\added(%rsp), %rdi
 107         movq %rdi, RIP(%rsp)
 108 
 109         
 110 
 111 
 112 
 113 
 114         subq $MCOUNT_INSN_SIZE, %rdi
 115         .endm
 116 
 117 .macro restore_mcount_regs
 118         movq R9(%rsp), %r9
 119         movq R8(%rsp), %r8
 120         movq RDI(%rsp), %rdi
 121         movq RSI(%rsp), %rsi
 122         movq RDX(%rsp), %rdx
 123         movq RCX(%rsp), %rcx
 124         movq RAX(%rsp), %rax
 125 
 126         
 127         movq RBP(%rsp), %rbp
 128 
 129         addq $MCOUNT_REG_SIZE, %rsp
 130 
 131         .endm
 132 
 133 #ifdef CONFIG_DYNAMIC_FTRACE
 134 
 135 ENTRY(function_hook)
 136         retq
 137 ENDPROC(function_hook)
 138 
 139 ENTRY(ftrace_caller)
 140         
 141         save_mcount_regs
 142 
 143 GLOBAL(ftrace_caller_op_ptr)
 144         
 145         movq function_trace_op(%rip), %rdx
 146 
 147         
 148         movq $0, %rcx
 149 
 150 GLOBAL(ftrace_call)
 151         call ftrace_stub
 152 
 153         restore_mcount_regs
 154 
 155         
 156 
 157 
 158 
 159 
 160 GLOBAL(ftrace_epilogue)
 161 
 162 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 163 GLOBAL(ftrace_graph_call)
 164         jmp ftrace_stub
 165 #endif
 166 
 167 
 168 
 169 
 170 
 171 WEAK(ftrace_stub)
 172         retq
 173 ENDPROC(ftrace_caller)
 174 
 175 ENTRY(ftrace_regs_caller)
 176         
 177         pushfq
 178 
 179         
 180         save_mcount_regs 8
 181         
 182 
 183 GLOBAL(ftrace_regs_caller_op_ptr)
 184         
 185         movq function_trace_op(%rip), %rdx
 186 
 187         
 188         movq %r15, R15(%rsp)
 189         movq %r14, R14(%rsp)
 190         movq %r13, R13(%rsp)
 191         movq %r12, R12(%rsp)
 192         movq %r11, R11(%rsp)
 193         movq %r10, R10(%rsp)
 194         movq %rbx, RBX(%rsp)
 195         
 196         movq MCOUNT_REG_SIZE(%rsp), %rcx
 197         movq %rcx, EFLAGS(%rsp)
 198         
 199         movq $__KERNEL_DS, %rcx
 200         movq %rcx, SS(%rsp)
 201         movq $__KERNEL_CS, %rcx
 202         movq %rcx, CS(%rsp)
 203         
 204         leaq MCOUNT_REG_SIZE+8*2(%rsp), %rcx
 205         movq %rcx, RSP(%rsp)
 206 
 207         ENCODE_FRAME_POINTER
 208 
 209         
 210         leaq (%rsp), %rcx
 211 
 212 GLOBAL(ftrace_regs_call)
 213         call ftrace_stub
 214 
 215         
 216         movq EFLAGS(%rsp), %rax
 217         movq %rax, MCOUNT_REG_SIZE(%rsp)
 218 
 219         
 220         movq RIP(%rsp), %rax
 221         movq %rax, MCOUNT_REG_SIZE+8(%rsp)
 222 
 223         
 224         movq R15(%rsp), %r15
 225         movq R14(%rsp), %r14
 226         movq R13(%rsp), %r13
 227         movq R12(%rsp), %r12
 228         movq R10(%rsp), %r10
 229         movq RBX(%rsp), %rbx
 230 
 231         restore_mcount_regs
 232 
 233         
 234         popfq
 235 
 236         
 237 
 238 
 239 
 240 
 241 
 242 GLOBAL(ftrace_regs_caller_end)
 243 
 244         jmp ftrace_epilogue
 245 
 246 ENDPROC(ftrace_regs_caller)
 247 
 248 
 249 #else 
 250 
 251 ENTRY(function_hook)
 252         cmpq $ftrace_stub, ftrace_trace_function
 253         jnz trace
 254 
 255 fgraph_trace:
 256 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 257         cmpq $ftrace_stub, ftrace_graph_return
 258         jnz ftrace_graph_caller
 259 
 260         cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
 261         jnz ftrace_graph_caller
 262 #endif
 263 
 264 GLOBAL(ftrace_stub)
 265         retq
 266 
 267 trace:
 268         
 269         save_mcount_regs
 270 
 271         
 272 
 273 
 274 
 275 
 276 
 277         movq ftrace_trace_function, %r8
 278         CALL_NOSPEC %r8
 279         restore_mcount_regs
 280 
 281         jmp fgraph_trace
 282 ENDPROC(function_hook)
 283 #endif 
 284 
 285 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 286 ENTRY(ftrace_graph_caller)
 287         
 288         save_mcount_regs
 289 
 290         leaq MCOUNT_REG_SIZE+8(%rsp), %rsi
 291         movq $0, %rdx   
 292         call    prepare_ftrace_return
 293 
 294         restore_mcount_regs
 295 
 296         retq
 297 ENDPROC(ftrace_graph_caller)
 298 
 299 ENTRY(return_to_handler)
 300         UNWIND_HINT_EMPTY
 301         subq  $24, %rsp
 302 
 303         
 304         movq %rax, (%rsp)
 305         movq %rdx, 8(%rsp)
 306         movq %rbp, %rdi
 307 
 308         call ftrace_return_to_handler
 309 
 310         movq %rax, %rdi
 311         movq 8(%rsp), %rdx
 312         movq (%rsp), %rax
 313         addq $24, %rsp
 314         JMP_NOSPEC %rdi
 315 END(return_to_handler)
 316 #endif